C/C++ Arena

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.

Previous: #define constants Next: Bitwise operators