Challenge 3: Why SQUARE(i++) Is Still Buggy Even Fully Parenthesized — Possible Solution ==================================================================== With SQUARE defined correctly as #define SQUARE(x) ((x) * (x)), SQUARE(i++) expands, via pure text substitution, to: ((i++) * (i++)) This is syntactically valid C -- the parentheses do fix the operator-precedence problem from Challenge 1 -- but it introduces a DIFFERENT bug entirely: the expression i++ now appears TWICE in the expanded code, and each occurrence is a SEPARATE increment of i. If i starts at 5, this expression increments i twice (to 7, not 6) and the multiplication uses two DIFFERENT values of i (5 and 6, in some order depending on evaluation rules) rather than squaring a single, consistent value. The programmer's clear intent -- "read i once, square it, and increment it once as a side effect" -- is not what actually happens; i has been incremented twice, and the "squared" result isn't even a real square of any single value i ever held. Why square(i++) as a genuine FUNCTION CALL would never have this problem: a real function receives its arguments by VALUE (per Chapter 5) -- C evaluates the expression i++ exactly ONCE, computes its result, and passes that single resulting value into the function's parameter. The function body then uses that one already-computed value as many times as it wants internally, with no possibility of the original expression i++ being re-evaluated a second time, because the function's parameter is a genuinely separate variable holding a copy, not a textual restatement of the caller's original expression. The root cause, stated plainly: a macro is text substitution, so writing an argument's NAME multiple times inside the macro body literally repeats the CALLER'S ORIGINAL EXPRESSION multiple times in the expanded code. A function call evaluates its argument expression exactly once, no matter how many times the parameter is referenced inside the function body -- a guarantee macros, being pure text substitution, structurally cannot offer. WHY THIS WORKS AS AN ANSWER ------------------------------ This shows the actual expanded text ((i++) * (i++)) to make the double increment concrete, explains the specific mechanism that makes a real function immune (evaluate-once-into-a-value semantics, tied back to Chapter 5's pass-by-value), and states the root cause (macros repeat the caller's literal expression; functions evaluate it once) rather than treating this as an unrelated, separate quirk from the parenthesization issue.