a macro and macro expansion
/ MAK-roh /
A macro is a named piece of text you set up with #define, so that wherever the name appears later, the preprocessor swaps it out for the text you gave. Macro expansion is that swapping happening. It is a find-and-replace that runs over your code before compilation, like a word processor's autocorrect that you yourself programmed. Write #define PI 3.14159 and every later PI literally becomes 3.14159 in the text handed to the compiler.
Macros come in two flavours. An object-like macro is a plain name standing in for some text, like #define BUFSIZE 1024. A function-like macro takes parentheses and arguments, like #define SQUARE(x) ((x)*(x)), and on use it pastes the argument text into the pattern. The crucial point is that this is still text pasting, not a real function call: no values are computed, no arguments are evaluated first. The text x is simply replaced character-for-character with whatever you put in the parentheses, and only then does the compiler read the result.
That textual nature is the source of every classic macro trap. If you write #define SQUARE(x) x*x (no parentheses) then SQUARE(a+b) expands to a+b*a+b, which is not the square at all because of operator precedence. If you call SQUARE(i++), the i++ gets pasted twice and i is incremented twice. Always parenthesise both the whole body and each argument, and never pass an expression with side effects. For constants, a const int or an enum is usually safer than a macro because it respects C's type and scope rules; for short code, an inline function avoids the double-evaluation trap entirely.
#define SQUARE(x) x*x /* BUG: no parentheses */ z = SQUARE(a+b); /* expands to: z = a+b*a+b; -- wrong! */ #define SAFE(x) ((x)*(x)) /* fix: SAFE(a+b) -> ((a+b)*(a+b)) */
A function-like macro pastes text, so missing parentheses let surrounding operators sneak in.
A function-like macro is not a function: it evaluates its arguments however many times they textually appear, so SQUARE(i++) increments i twice, a bug a real function never has.