Step 2 of 5
Macro pitfalls
Macros can take parameters, which makes them look like functions:
#define SQUARE(x) x * x
But they aren't functions. The preprocessor pastes the argument's text into the body, without evaluating it first. That leads to surprises:
SQUARE(1 + 2) // becomes 1 + 2 * 1 + 2 which is 5, not 9
100 / SQUARE(5) // becomes 100 / 5 * 5 which is 100, not 4
The fix is to put parentheses around every use of each parameter and around the whole body:
#include <stdio.h>
#define BAD_SQUARE(x) x * x
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main(void) {
printf("%d %d\n", BAD_SQUARE(1 + 2), SQUARE(1 + 2));
printf("%d %d\n", 100 / BAD_SQUARE(5), 100 / SQUARE(5));
printf("%d\n", MAX(3, 7) * 2);
return 0;
}
5 9
100 4
14
Another trap: arguments evaluated twice
MAX(i++, j) expands to use i++ twice, so i may be incremented twice. A real function evaluates each argument exactly once. This is why modern C code prefers static inline functions over function-like macros whenever possible: they have types, evaluate arguments once, and show up in the debugger. Macros remain useful for things functions can't do, but always write them defensively.
Your turn: DOUBLE(3 + 4) * 2 should be 28, but this prints 18. Fix the DOUBLE macro.