5.1.28 · Coding › C Programming
Dono macros aur inline functions ka kaam hai normal function call ka cost bachana — chhoti, baar-baar use hone wali operations ke liye. Ek normal function call mein overhead hota hai: stack pe arguments push karo, jump karo, registers save karo, return karo, pop karo. Kisi cheez ke liye jaise "is number ka square nikalo", call karne ka cost actual kaam se zyada ho sakta hai. Isliye hum compiler/preprocessor se kehte hain ki code ko directly wahin paste kar do jahan use ho raha hai , door jump karne ki jagah.
Gehra fark yeh hai: ek macro preprocessor ki taraf se text substitution hai (yeh tab hota hai jab compiler ne asli C dekhi bhi nahi hoti ), jabki ek inline function ek asli function hai jise compiler jagah pe expand karne ka choice kar sakta hai — type checking, scoping, aur har argument ki ek baar evaluation ko maintain karte hue.
Definition Macro (function-like)
Ek #define directive jo preprocessor handle karta hai. Yeh andha text replacement karta hai — C types, scope, ya evaluation rules ka koi gyan nahi.
#define SQUARE ( x ) ((x) * (x))
Definition Inline function
Ek normal function jisme inline keyword hota hai, jo compiler ko suggest karta hai ki call overhead se bachne ke liye body ko call site pe copy kar do — lekin phir bhi ek sachi, type-checked function rehti hai.
static inline int square ( int x ) { return x * x; }
Intuition Macros kyun dangerous hain
Kyunki preprocessor sirf text jaanta hai, woh operator precedence ya aapka argument kitni baar evaluate ho raha hai yeh nahi samajh sakta. Compiler-based inline function har argument ko bilkul ek baar evaluate karta hai aur types ka bhi khayal rakhta hai.
Worked example Precedence trap
#define BAD ( x ) x * x // no parentheses
int r = BAD ( 2 + 3 ); // expands to 2 + 3 * 2 + 3
Yeh step kyun? Text substitution se milta hai 2 + 3 * 2 + 3 = 2 + 6 + 3 = 11, nahi 25 .
Fix: sab kuch parenthesize karo → #define SQ(x) ((x)*(x)) deta hai ((2+3)*(2+3)) = 25. ✅
Worked example Double-evaluation trap
#define SQ ( x ) ((x) * (x))
int i = 3 ;
int r = SQ (i ++ ); // expands to ((i++)*(i++))
Yeh step kyun? i++ do baar aata hai, isliye i do baar increment hota hai — undefined/unexpected result. Ek inline function square(i++) mein i ek baar increment hota hai kyunki argument call se pehle evaluate hota hai. ✅
Preprocessor pehle chalta hai → #define macros expand karta hai (pure text).
Compiler phir expanded text dekhta hai → type checking karta hai, phir shayad functions inline karta hai.
Toh macros type checking shuru hone se pehle resolve ho jaate hain; inline functions type system ke andar rehte hain.
Aspect
Macro (#define)
Inline function
Handle karta hai
Preprocessor
Compiler
Type checking
❌ Nahi
✅ Poori
Argument evaluate hota hai
Shayad kai baar
Ek baar
Scope respect karta hai
❌ (global text)
✅
Debuggable / breakpoints
❌ Mushkil
✅ Haan
inline ek... hai
(n/a)
request , compiler ignore kar sakta hai
Address hai / & le sakte hain
❌
✅
Types ke liye generic
✅ (kisi bhi type ke liye kaam karta hai)
❌ (ek type, jab tak overload na ho — C mein nahi)
Intuition Kab kaun jeetta hai (80/20)
Inline function = default modern choice: safe, typed, debuggable.
Macro = jab aapko aisi cheez chahiye jo function nahi kar sakta : type-generic code, stringizing #x, token-pasting a##b, ya conditional compilation.
Worked example MAX as macro (type-generic lekin risky)
#define MAX ( a , b ) ((a) > (b) ? (a) : (b))
MAX (p ++ , q ++ ) // ⚠ p/q mein se ek do baar increment hoga
Yeh step kyun? Jo ?: mein jeetta hai woh "return" hote waqt dobara evaluate hota hai. Dobara double evaluation.
Worked example MAX as inline (safe)
static inline int imax ( int a , int b ) { return a > b ? a : b; }
imax (p ++ , q ++ ); // har ek bilkul ek baar evaluate hota hai ✅
Yeh step kyun? Arguments p++, q++ body chalne se pehle ek baar parameters mein compute ho jaate hain.
Common mistake Common galtiyon ko samjho
"inline guarantee karta hai ki function inline ho jaayega."
Kyun sahi lagta hai: keyword literally "inline" kehta hai. Sach: inline sirf ek hint hai; compiler ise ignore kar sakta hai (jaise recursive ya badi functions). Yeh linkage rules ko bhi affect karta hai, koi hard inlining order nahi. Fix: compiler ke optimizer pe rely karo; inline intent ke liye use karo, control ke liye nahi.
"Macros hamesha functions se tez hote hain."
Kyun sahi lagta hai: koi call overhead nahi. Sach: ek inline function ka bhi koi call overhead nahi hota jab inline kiya jaaye, aur arguments ko dobara evaluate karne se bhi bachata hai, aksar behtar code produce karta hai. Fix: inline prefer karo; macros tabhi lo jab non-function powers chahiye.
"Macro ko statement ki tarah semicolon chahiye."
Kyun sahi lagta hai: yeh code jaisa dikhta hai. Sach: #define MAX(a,b) (...) ek expression hai; define ke andar ; add karna expressions ko tod deta hai. Multi-statement macros ke liye do { ... } while(0) idiom use karo.
do{...}while(0) idiom
#define SWAP ( a , b , T ) do { T t = (a); (a) = (b); (b) = t; } while ( 0 )
if (x) SWAP (p,q, int ); else foo (); // sahi kaam karta hai
Yeh step kyun? do{...}while(0) mein wrap karne se ek multi-statement macro ek single statement ki tarah behave karta hai, toh if/else pairing valid rehti hai aur trailing ; consume ho jaata hai.
Recall Ek 12-saal ke bachche ko samjhao (hidden)
Socho ek recipe kehti hai "SQUARE(amount of sugar) daalo". Ek macro ek laparwah helper ki tarah hai jo literally aapke words dobara likhta hai — agar aapne "1+1 cups" kaha, toh woh likhta hai "1+1 × 1+1 cups" aur math galat kar deta hai. Ek inline function ek samajhdar helper hai jo pehle figure out karta hai ki aapka matlab 2 cups tha, phir use square karke 4 karta hai — har baar, sahi tarike se. Dono aapko door ki kitchen ka chakkar bachate hain (function call), lekin samajhdar helper galti nahi karta.
"Pre-Paste, Com-Check."
Macro = Preprocessor Pastes text (Parens + double-eval Perils).
Inline = Compiler Checks types (Counts each arg once).
Macro ko kaun process karta hai aur inline function ko kaun?
#define SQ(x) x*x ke saath SQ(2+3) kyun toot jaata hai?
SQ(i++) macro ke taur pe dangerous kyun hai lekin inline function ke taur pe safe?
Kya inline ek guarantee hai?
Who handles macros, preprocessor or compiler? Preprocessor — compilation se pehle pure text substitution.
Who handles inline functions? Compiler , jo body ko call site pe expand karne ka choice kar sakta hai.
Why must macro parameters and the whole body be parenthesized? Operator precedence preserve karne ke liye; text substitution warna SQ(2+3) jaisi expressions tod deta hai.
What does SQ(2+3) expand to with #define SQ(x) x*x? 2+3*2+3 = 11, 25 nahi.
Why is SQ(i++) unsafe as a macro? i++ do baar substitute hota hai → (i++)*(i++), side effect do baar evaluate hota hai (undefined/unexpected).
How many times does an inline function evaluate each argument? Bilkul ek baar — body chalne se pehle arguments compute ho jaate hain.
Is inline a command or a request? Ek request/hint ; compiler ise ignore kar sakta hai.
Give one thing macros can do that functions cannot. Type-generic code, stringizing #x, token pasting ##, ya conditional compilation.
Which is easier to debug, macro or inline function? Inline function — aap breakpoints set kar sakte ho aur yeh scope/types respect karta hai.
What idiom makes a multi-statement macro a single safe statement? do { ... } while(0).
C Preprocessor — #define, #include, conditional compilation
Operator Precedence in C — macro parens kyun matter karte hain
Function Call Overhead — woh cost jo dono techniques remove karti hain
Undefined Behavior in C — double-evaluation side effects
const and constexpr — constant macros ke typed alternatives
Compiler Optimization — jab inline actually honor kiya jaata hai