Exercises — Preprocessor directives — #define, #ifdef, #ifndef, #include guards
5.1.27 · D4· Coding › C Programming › Preprocessor directives — #define, #ifdef, #ifndef, #include
Ek law yaad rakho jo yahan sab kuch govern karta hai: preprocessor compiler ke run hone se pehle blind text substitution aur text deletion karta hai. Ise C nahi aata. Yeh sirf tokens aur # lines jaanta hai.
L1 — Recognition
Exercise 1.1
Ek sentence mein batao ki har line kya karti hai:
#define MAX 100
#ifdef DEBUG
#ifndef CONFIG_H
#endifRecall Solution
#define MAX 100→ jahan bhi baad mein tokenMAXaata hai, wahan100text paste kar do.#ifdef DEBUG→ aane wali lines ko tabhi rakho agarDEBUGabhi defined hai; warna unhe delete kar do.#ifndef CONFIG_H→ aane wali lines ko tabhi rakho agarCONFIG_Hdefined nahi hai.#endif→ sabse recent conditional block band karo.
Exercise 1.2
Inn mein se kaun se preprocessor directives hain, aur kaun se ordinary C hain?
(a) #include <stdio.h> (b) int x = 5; (c) #define N 8 (d) return 0;
Recall Solution
Directives (# se shuru hote hain, compilation se pehle handle hote hain): (a) aur (c).
Ordinary C statements (compiler handle karta hai): (b) aur (d).
Pahchaanne ki nishani leading # hai.
L2 — Application
Exercise 2.1
Preprocessing ke baad, y ki jagah exact kya text aayega?
#define DOUBLE(x) (x) + (x)
int y = DOUBLE(5) * 3;Substituted text do aur number evaluate karo.
Recall Solution
DOUBLE(5) substitute karo → (5) + (5):
Ab compiler precedence apply karta hai: * pehle + se, toh (5) * 3 = 15, phir (5) + 15 = 20.
Answer: 20 — 30 nahi. Body outer parentheses mein wrap nahi thi, isliye * 3 sirf doosre (x) ko pakad gaya.
Exercise 2.2
Haath se evaluate karo:
#define HALF(x) x / 2
int z = HALF(6 + 4);Recall Solution
Blind substitution → int z = 6 + 4 / 2;
Precedence: / pehle + se, toh 4 / 2 = 2, phir 6 + 2 = 8.
Answer: 8 (5 nahi). Fix hai #define HALF(x) ((x) / 2).
Exercise 2.3
w mein kaunsa number end up hoga?
#define SQUARE(x) ((x) * (x))
int w = SQUARE(3 + 1);Recall Solution
Substitute karo → ((3 + 1) * (3 + 1)) → (4 * 4) = 16. Full parenthesisation ise real squaring ki tarah behave karata hai.
Exercise 2.4
Kaun si lines compiler tak survive karti hain?
#define VERBOSE
#ifdef VERBOSE
printf("A\n");
#endif
#ifdef QUIET
printf("B\n");
#endifRecall Solution
VERBOSE defined hai → printf("A\n"); survive karta hai.
QUIET kabhi define nahi hua → #ifdef QUIET block text ke roop mein delete ho jata hai; printf("B\n"); compiler tak pahunchta hi nahi.
Surviving code: sirf printf("A\n");. Yahi mechanism hai Conditional compilation for cross-platform code ke peeche.
L3 — Analysis
Exercise 3.1
Yeh ek confusing error ke saath compile hota hai. Explain karo ki compiler actually kaunsa text dekhta hai.
#define SIZE 32;
int arr[SIZE];Recall Solution
SIZE ke liye replacement text 32; hai (semicolon included). Toh int arr[SIZE]; ban jaata hai:
Yeh valid C nahi hai — brackets ke andar ; ise tod deta hai. #define ek C statement nahi hai, isliye iske ant mein semicolon nahi lagta. Fix: #define SIZE 32.
Exercise 3.2
Do headers, dono ek hi same guard tag use kar rahe hain:
/* a.h */ /* b.h */
#ifndef HEADER_H #ifndef HEADER_H
#define HEADER_H #define HEADER_H
struct A { int p; }; struct B { int q; };
#endif #endifmain.c pehle #include "a.h" karta hai phir #include "b.h". Kya struct B compile hoga? Explain karo.
Recall Solution
Nahi — struct B silently drop ho jaata hai.
a.hpehle paste hota hai:HEADER_Hundefined → guard true →HEADER_Hdefine karo,struct Arakho.b.hbaad mein paste hota hai:HEADER_Hab defined hai →#ifndef HEADER_Hfalse hai →b.hki poori body (includingstruct B) delete ho jaati hai. Tag unique hona chahiye (jaiseA_H,B_H) — neeche include-order picture dekho.

Exercise 3.3
main.c ko preprocess karne ke baad struct Point kitni baar appear hota hai?
/* point.h */
#ifndef POINT_H
#define POINT_H
struct Point { int x, y; };
#endif
/* main.c */
#include "point.h"
#include "point.h" /* included twice on purpose */Recall Solution
Exactly ek baar.
- 1st include:
POINT_Hundefined → guard true →POINT_Hdefine karo, struct rakho. - 2nd include:
POINT_Hab defined hai → guard false → body delete. Guard "redefinition ofstruct Point" error prevent karta hai jo bina guard ke aata. Dekho Header files and translation units.
L4 — Synthesis
Exercise 4.1
matrix_utils.h naam ke ek header ke liye correct include guard likho jo struct Matrix { int rows, cols; }; define karta ho.
Recall Solution
#ifndef MATRIX_UTILS_H
#define MATRIX_UTILS_H
struct Matrix { int rows, cols; };
#endif /* MATRIX_UTILS_H */Tag filename se derive hota hai (uppercase, . → _) taaki project mein unique rahe.
Exercise 4.2
Ek macro MIN(a, b) likho jo do values mein se choti return kare aur MIN(x+1, y-2) jaise expressions ke liye safe ho.
Recall Solution
#define MIN(a, b) (((a) < (b)) ? (a) : (b))Har argument wrap hai, aur poora conditional expression bhi wrap hai. MIN(3+1, 2*5) se check karo → (((3+1) < (2*5)) ? (3+1) : (2*5)) → (4 < 10) ? 4 : 10 → 4.
(Jaanne wali caveat: kyunki a aur b do baar paste hote hain, MIN(i++, j) mein i++ do baar evaluate hota hai — ek reason ki inline functions aksar safer hoti hain.)
Exercise 4.3
Ek "default-with-override" configuration block likho: LOG_LEVEL ko 2 set karo jab tak build command line se apni value supply na kare.
Recall Solution
#ifndef LOG_LEVEL
#define LOG_LEVEL 2
#endifAgar build -DLOG_LEVEL=4 pass kare (dekho Build flags -D and the command line), toh LOG_LEVEL already defined hai → #ifndef false hai → default skip hota hai aur 4 wins. Warna default 2 ho jaata hai.
L5 — Mastery
Exercise 5.1
Ise poora trace karo. Exact surviving C code kya hai, aur total ki value kya hai?
#define SCALE 3
#ifndef LIMIT
#define LIMIT 10
#endif
#define AREA(w, h) ((w) * (h))
#ifdef SCALE
int total = AREA(2 + 1, LIMIT) * SCALE;
#else
int total = 0;
#endifMaan lo LIMIT externally supply nahi hua tha.
Recall Solution
Step 1 — LIMIT undefined → guard true → #define LIMIT 10.
Step 2 — SCALE defined hai → #ifdef SCALE branch rakho, #else delete karo.
Step 3 — int total = AREA(2 + 1, LIMIT) * SCALE; mein macros expand karo:
AREA(2 + 1, LIMIT)→((2 + 1) * (LIMIT))→((2 + 1) * (10))SCALE→3Surviving code: Step 4 — compiler evaluate karta hai:(3 * 10) = 30, phir30 * 3 = 90. Answer: 90.
Exercise 5.2
Ab maan lo build gcc -DLIMIT=4 prog.c se invoke hoti hai. Exercise 5.1 ka total dobara nikalo.
Recall Solution
-DLIMIT=4 LIMIT ko 4 ke roop mein define karta hai file ka text dekhne se pehle.
#ifndef LIMITab false hai → default#define LIMIT 10skip hota hai →LIMIT4rehta hai.SCALEab bhi defined hai → same branch survive karta hai. Substituted:int total = ((2 + 1) * (4)) * 3;→(3 * 4) = 12, phir12 * 3 = 36. Answer: 36. Yeh dikhata hai kaise ek command-line flag compiled result ko rewire karta hai — yahi point hai Build flags -D and the command line ka.
Exercise 5.3
Build pipeline mein, neeche wala bug kis stage pe pakda jaata hai, aur kyun?
#define GREET printf("hi")
int main(void) { GREET } /* note: no semicolon after GREET */Recall Solution
Preprocessor khushi se produce karta hai:
Koi # error nahi hoti — text substitution legal hai. Bug missing semicolon hai, jo C ka ek syntax rule hai. Toh yeh baad mein, compiler stage (parsing) pe pakda jaata hai, preprocessor se nahi. Lesson: preprocessor kabhi C grammar validate nahi karta; yeh sirf paste aur delete karta hai. Fix: #define GREET printf("hi"); ya call site pe ; likho.
Recall Feynman self-check
Solutions cover karo aur khud se har exercise ke teen questions poochho: Preprocessor kaunsa text paste ya delete karta hai? Compiler phir kya evaluate karta hai? Kaunsa number/answer nikalta hai? Agar tum teeno ko clearly narrate kar sako, tum is topic ke malik ho.
Flashcards
DOUBLE(5) * 3 mein jab #define DOUBLE(x) (x) + (x) ho, value kya hai?
* 3 sirf ek term se bind hota hai.#define HALF(x) x / 2, HALF(6 + 4) kya deta hai?
4 / 2 + se pehle hota hai.#define SIZE 32; int arr[SIZE]; ko kyun break karta hai?
; bhi substitute ho jaata hai → int arr[32;];, invalid.Agar do headers #ifndef HEADER_H share karein, doosre ka kya hoga?
Guards ke saath, ek header ke do #include ke baad struct kitni baar appear hoga?
Expression-safe MIN macro sahi form?
#define MIN(a, b) (((a) < (b)) ? (a) : (b)).LOG_LEVEL ke liye default-with-override pattern?
#ifndef LOG_LEVEL / #define LOG_LEVEL 2 / #endif.