Macro Parentheses in C – Why SQ(2 + 3) Gives 11, Not 25

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?

  1. 25
  2. 11
  3. 10
  4. 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

Recommended Books

This question is #35 in the C Programming Quiz App — 155 questions with explanations covering preprocessor, pointers, memory, and more.
Download on Google Play →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>