Macros & Preprocessor
Macro क्या है? (त्वरित याद)
Macro एक नियम है जो आप #define से बनाते हैं और C preprocessor उसका इस्तेमाल compiler चलने से पहले आपके code में text बदलने के लिए करता है। अगर #include और include guards जैसे preprocessor basics नए हैं, तो पहले preprocessor directives पढ़ें। यह lesson खासकर macros पर केंद्रित है — preprocessor का सबसे शक्तिशाली और सबसे ख़तरनाक हिस्सा।
Object-like macros (constants)
सबसे सरल macros बस किसी fixed value को एक नाम देते हैं। इन्हें object-like macros कहते हैं।
#include <stdio.h>
#define PI 3.14159
#define GREETING "Hello!"
int main() {
printf("PI = %f\n", PI);
printf("%s\n", GREETING);
return 0;
}PI = 3.141590
Hello!
Compile से पहले preprocessor हर PI को 3.14159 और हर GREETING को "Hello!" से बदल देता है।
Function-like macros
Macros arguments भी ले सकते हैं, functions जैसे दिखते हुए — पर ये अब भी सिर्फ़ text replacement हैं।
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
printf("Square = %d\n", SQUARE(5));
printf("Max = %d\n", MAX(10, 20));
return 0;
}Square = 25
Max = 20
Parentheses क्यों ज़रूरी हैं
यह macro का नंबर-एक जाल है। चूँकि macros अंधा text substitution हैं, parentheses न होने पर चुपचाप गलत जवाब मिल सकते हैं।
#include <stdio.h>
#define BAD(x) x * x // बिना parentheses
#define GOOD(x) ((x) * (x)) // सुरक्षित
int main() {
printf("BAD(2+3) = %d\n", BAD(2+3)); // 2+3*2+3 = 11
printf("GOOD(2+3) = %d\n", GOOD(2+3)); // (2+3)*(2+3) = 25
return 0;
}BAD(2+3) = 11
GOOD(2+3) = 25
Function-like macro में हर argument और पूरे body को parentheses में लपेटें। यह एक आदत ज़्यादातर macro bugs रोक देती है।
# और ## operators
दो विशेष operators सिर्फ़ macros के अंदर होते हैं। # argument को string बना देता है; ## दो tokens को जोड़ देता है।
#include <stdio.h>
#define SHOW(x) printf(#x " = %d\n", x) // stringize
#define JOIN(a,b) a ## b // token paste
int main() {
int value = 42;
SHOW(value); // छापता है: value = 42
int JOIN(my, Num) = 7; // बनता है: int myNum = 7;
printf("myNum = %d\n", myNum);
return 0;
}value = 42
myNum = 7
ध्यान दें कैसे #x ने text "value" छापा, और JOIN(my, Num) ने identifier myNum बनाया।
Macros बनाम functions
| बिंदु | Macro | Function |
|---|---|---|
| कब चलता है | Compilation से पहले (text) | Run time पर |
| Type checking | नहीं | हाँ |
| गति | Call overhead नहीं | थोड़ा call overhead |
| Debugging | कठिन | आसान |
| Side-effect सुरक्षा | जोखिम भरा | सुरक्षित |
खतरनाक pitfalls
Parentheses के अलावा macros का एक और classic जाल है: एक से ज़्यादा बार इस्तेमाल हुए arguments एक से ज़्यादा बार evaluate हो सकते हैं।
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
int main() {
int n = 4;
printf("%d\n", SQUARE(n++)); // ((n++) * (n++)) बन जाता है -- असुरक्षित!
return 0;
}चूँकि SQUARE(n++) ((n++) * (n++)) में expand होता है, n दो बार बढ़ता है और result undefined होता है। Macro को कभी side effect वाले expressions (जैसे n++) न दें। असली function में यह समस्या नहीं होती।
सारांश
- Macro एक
#definetext-replacement नियम है जो compilation से पहले संभाला जाता है। - Object-like macros constants को नाम देते हैं; function-like macros arguments लेते हैं।
- हमेशा हर argument और पूरे macro body को parentheses में रखें।
#argument को string बनाता है;##tokens को जोड़ता है।- Macros में type checking नहीं होती और arguments दो बार evaluate हो सकते हैं — संदेह हो तो functions पसंद करें।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
C में macro क्या है?
#define से बनाया जाता है और preprocessor उसे compilation से पहले एक text टुकड़े से बदल देता है। यह #define PI 3.14 जैसा सरल constant हो सकता है, या arguments लेने वाला function-like macro। Compiler macro नाम कभी नहीं देखता — सिर्फ़ उसका replacement text।C में macro और function में क्या अंतर है?
Function-like macros में इतने parentheses क्यों ज़रूरी हैं?
#define SQ(x) x*x में SQ(2+3) बन जाता है 2+3*2+3 = 11, न कि 25। हर argument और पूरे body को parentheses में लपेटना — ((x)*(x)) — इसे रोकता है।Macros में # और ## operators क्या करते हैं?
# operator macro argument को string बना देता है ("stringize"), तो #x बन जाता है "x"। ## operator दो tokens को एक में जोड़ देता है ("token pasting"), तो a ## b बन जाता है ab। ये advanced macros में names और debug messages बनाने में इस्तेमाल होते हैं।क्या C में macros बुरी practice मानी जाती है?
const या enum पसंद करते हैं, और छोटे operations के लिए inline function सुरक्षित है। Macros conditional compilation और कुछ ऐसे कामों के लिए उपयोगी रहते हैं जो functions नहीं कर सकते, पर जटिल macros का ज़्यादा इस्तेमाल code को पढ़ने और debug करने में कठिन बना देता है।