Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Expansion Mechanics

โญโญโญ advancedโณ 15 min read๐Ÿ“ Lesson 178 of 225

Argument expansion order, the double-expansion idiom, stringize and paste โ€” what the preprocessor actually does with your text.

Arguments expand before substitution โ€” except with # and

SQUARE(x) ((x) * (x)) replaces x with the already expanded argument โ€” unless x is used with # (stringize) or ## (paste), where it stays raw. This subtlety is why the classic double-expansion wrapper exists:

#define STR_(x) #x          /* x stays unexpanded: becomes "x" */
#define STR(x)  STR_(x)     /* x expands first, then stringizes */

STR(__LINE__) gives "14"; STR_(__LINE__) gives "LINE".

Parenthesize everything

#define BAD(a, b) a + b and BAD(1, 2) * 3 expands to 1 + 2 * 3. Every parameter reference gets parentheses; the whole replacement gets parentheses. Macro code that violates this is not stylistically wrong โ€” it computes wrong answers.

Multi-line and do-while

Statement-shaped macros wrap in do { ... } while (0) so if (x) MACRO(); else ... still parses โ€” a plain { } would break the semicolon. This is not superstition; it is syntax maintenance.

โšก Now practice

Ready to Code
Preprocessor Mechanics DrillsExpansion order, safe macro shapes, variadic forwarding, and assertions โ€” mechanisms verified by their expansion results.
4 challenges ยท ยท ~22 min