A macro that squares a number — what could go wrong? Everything, because the preprocessor doesn’t square numbers; it pastes text. This question from our C Programming Quiz App is the canonical macro trap, the one that turns SQ(2 + 3) into something that isn’t 25 — and the reason every style guide screams “parenthesize your macro parameters”.
The Quiz Question
#define SQ(x) x*x
printf("%d", SQ(2 + 3));
What is printed by this code?
- 25
- 11
- 10
- Compile error
The Correct Answer: 11
A macro is textual substitution — the preprocessor replaces SQ(2 + 3) with the body, pasting 2 + 3 wherever x appears, with no parentheses added:
SQ(2 + 3) → 2 + 3*2 + 3
Then ordinary precedence applies: multiplication first, so 2 + 6 + 3 = 11. Verified on gcc 13.3 and Apple clang 21 (and you can watch the substitution yourself with gcc -E, which stops after preprocessing):
$ gcc -ansi -Wall -Wextra sq.c && ./a.out 11
Why Each Wrong Answer Is Wrong
Why not 25?
25 is what a function would produce — int sq(int x) { return x*x; } evaluates its argument first (5), then squares it. The macro never evaluates 2 + 3 as a unit; it splices the tokens into the expression raw. 25 is also what the properly written macro gives:
#define SQ(x) ((x)*(x))
$ ./a.out 25
The inner parentheses protect the parameter; the outer ones protect the whole expansion from surrounding operators (imagine 10 / SQ(5) with the body (x)*(x) — it would parse as (10 / 5) * 5).
Why not 10?
10 comes from misapplying precedence to the expanded text — reading 2 + 3*2 + 3 as (2+3) * (2+3)… and then miscomputing, or as strictly left-to-right ((2+3)*2)+3 = 13-style arithmetic gone wrong. Whatever the route, the expansion has exactly one multiplication, 3*2, and it binds tighter than both additions.
Why not a compile error?
The expansion 2 + 3*2 + 3 is a perfectly valid expression — that’s precisely the danger. The preprocessor is oblivious to meaning, and the compiler sees only legal (wrong) code. Neither stage has anything to complain about; both compilers are silent under -Wall -Wextra.
The Second Trap: Parentheses Don’t Fix Side Effects
Even the corrected ((x)*(x)) pastes the argument twice. Pass anything with a side effect and it happens twice:
int i = 3;
printf("%d", SQ(i++)); /* expands to ((i++)*(i++)) */
$ ./a.out 12 (i is now 5)
Two increments, an unsequenced-modification warning from both compilers (gcc: -Wsequence-point, clang: -Wunsequenced), and formally undefined behavior — the same rule as the x++ + ++x question. This is why modern C prefers static inline functions for anything computational: they evaluate arguments exactly once, obey types, and optimize identically. Macros keep two legitimate niches — compile-time constants (the object-like #define MAX kind) and token-level tricks functions can’t do.
Frequently Asked Questions
Why does SQ(2 + 3) with #define SQ(x) x*x give 11?
The preprocessor substitutes text, producing 2 + 3*2 + 3. Multiplication binds first: 2 + 6 + 3 = 11. No evaluation of the argument happens before substitution.
How should function-like macros be written?
Parenthesize every parameter and the whole body: #define SQ(x) ((x)*(x)). The inner parentheses defend against operators inside the argument; the outer ones defend against operators around the call site.
Are parenthesized macros completely safe?
No — the argument text is still pasted once per occurrence, so SQ(i++) increments twice and is undefined behavior. For computations, prefer a static inline function, which evaluates its argument exactly once.
Related Reading
- #define in C – How Object-Like Macros Work
- Sequence Points in C – Why x++ + ++x Is Undefined
- C Program to Demonstrate the #define Preprocessor
- C Aptitude Questions and Answers
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #35 in the C Programming Quiz App — 155 questions with explanations covering preprocessor, pointers, memory, and more.
Download on Google Play →