5.1.27 · D4 · HinglishC Programming

ExercisesPreprocessor directives — #define, #ifdef, #ifndef, #include guards

2,379 words11 min read↑ Read in English

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
#endif
Recall Solution
  • #define MAX 100 → jahan bhi baad mein token MAX aata hai, wahan 100 text paste kar do.
  • #ifdef DEBUG → aane wali lines ko tabhi rakho agar DEBUG abhi defined hai; warna unhe delete kar do.
  • #ifndef CONFIG_H → aane wali lines ko tabhi rakho agar CONFIG_H defined 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: 2030 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");
#endif
Recall 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                    #endif

main.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.

  1. a.h pehle paste hota hai: HEADER_H undefined → guard true → HEADER_H define karo, struct A rakho.
  2. b.h baad mein paste hota hai: HEADER_H ab defined hai → #ifndef HEADER_H false hai → b.h ki poori body (including struct B) delete ho jaati hai. Tag unique hona chahiye (jaise A_H, B_H) — neeche include-order picture dekho.
Figure — Preprocessor directives — #define, #ifdef, #ifndef, #include guards

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_H undefined → guard true → POINT_H define karo, struct rakho.
  • 2nd include: POINT_H ab defined hai → guard false → body delete. Guard "redefinition of struct 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 : 104. (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
#endif

Agar 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;
#endif

Maan 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))
  • SCALE3 Surviving code: Step 4 — compiler evaluate karta hai: (3 * 10) = 30, phir 30 * 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 LIMIT ab false hai → default #define LIMIT 10 skip hota hai → LIMIT 4 rehta hai.
  • SCALE ab bhi defined hai → same branch survive karta hai. Substituted: int total = ((2 + 1) * (4)) * 3;(3 * 4) = 12, phir 12 * 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?
20 — missing outer parens ki wajah se * 3 sirf ek term se bind hota hai.
#define HALF(x) x / 2, HALF(6 + 4) kya deta hai?
8, kyunki 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?
Uski body delete ho jaati hai — tag pehle wale se already defined hai.
Guards ke saath, ek header ke do #include ke baad struct kitni baar appear hoga?
Exactly ek baar.
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.
AREA(2+1, 10) * 3 jab #define AREA(w,h) ((w)*(h)) aur SCALE=3 ho?
90.
Same as above lekin -DLIMIT=4 toh h=4?
36.
Macro expansion ke baad missing semicolon kis stage pe pakdi jaati hai?
Compiler se, preprocessor se nahi.