Given #define SQUARE(x) x*x, what does SQUARE(a+1) expand to? Explain how the preprocessor works and when you should use an inline function or const instead of a macro.
Show the explanation
The preprocessor runs before the compiler and does plain text substitution. It has no idea about types, scope or evaluation.
Trap 1: missing parentheses. SQUARE(a+1) becomes a+1*a+1, which is 2a + 1, not (a+1)². The fix is to wrap every parameter and the whole body in parentheses:
#define SQUARE(x) ((x) * (x))Trap 2: arguments evaluated more than once. Even the fixed macro expands SQUARE(i++) to ((i++) * (i++)). That modifies i twice without sequencing, which is undefined behaviour. No amount of parentheses fixes this.
A better tool, the inline function
static inline int square(int x) { return x * x; }- The argument is evaluated exactly once.
- It is type-checked, and you can step into it in a debugger.
- The compiler can still inline it, so there is usually no call overhead.
Constants: prefer const int MAX = 100; or an enum { MAX = 100 }; over #define MAX 100 when you want type safety and debugger visibility. (In C, a const int cannot size a file-scope array; an enum constant can.)
What macros are still good for
- Include guards (
#ifndef HEADER_H…) and conditional compilation (#ifdef DEBUG). - Using
__FILE__and__LINE__in logging macros. - Stringising (
#x) and token pasting (a##b). - Multi-statement macros wrapped in
do { ... } while (0), so they behave like a single statement after anif.
Original UniCircle question. Last reviewed 22 Oct 2026.
