Macros with side effects: what does this program output, and why is it dangerous?\n\n#include<stdio.h>\n#define CUBE(x) (xxx)\n\nint main()\n{\n int a, b = 3;\n a = CUBE(b++); // expands to (b++b++b++) → undefined behavior\n printf("%d, %d\n", a, b);\n return 0;\n}\n\nChoose the most appropriate output often seen on popular compilers, noting the caveat in the explanation.

Difficulty: Hard

Correct Answer: 27, 6

Explanation:


Introduction / Context:
This example highlights why macros that evaluate their arguments multiple times are dangerous. Using an expression with side effects (like b++) inside a macro that repeats the argument leads to undefined behavior (UB) in C, because the variable b is modified multiple times without an intervening sequence point.



Given Data / Assumptions:

  • Macro: #define CUBE(x) (xxx).
  • Call: CUBE(b++).
  • Post-increment changes b after yielding its old value; the macro expands to (b++b++b++).
  • Order of evaluation of operands for * is unspecified in C.


Concept / Approach:
Because the same scalar (b) is modified more than once between sequence points, the behavior is undefined. Different compilers, targets, or optimization levels may compute different results. Some will evaluate operands in an order that accidentally produces the numeric cube 27 while applying three increments, ending with b = 6; others might produce 60 with b = 6, or something else entirely.



Step-by-Step Solution:
Textual expansion → (b++ * b++ * b++).Due to UB, no single portable step-by-step evaluation exists.On some common left-to-right evaluations of values, compilers may emit 27 for a while still incrementing three times, leaving b = 6; the printed pair can appear as "27, 6".



Verification / Alternative check:
Rewrite as a function: int cube(int x){ return xxx; } then call a = cube(b++); This evaluates b++ once, typically yielding a = 27 and b = 4 portably. Or use a safer macro: #define CUBE(x) ((x)(x)(x)) and avoid passing expressions with side effects.



Why Other Options Are Wrong:
"Error": The code compiles; the problem is runtime UB, not a compile-time error."27, 4" reflects function-like evaluation (argument used once), not the macro expansion that repeats x."9, 4" is not the cube and ignores additional increments.



Common Pitfalls:
Assuming operand evaluation order for * is left-to-right; passing ++ or -- into macros that use arguments multiple times; believing that UB has a consistent result across compilers.



Final Answer:
27, 6

More Questions from C Preprocessor

Discussion & Comments

No comments yet. Be the first to comment!
Join Discussion