liveBook · Manning

Do-while(false) trick

As explained in Modern C, Third Edition

A do-while macro wrapper is a macro pattern that encloses multiple statements in a single statement-like construct using a do loop whose condition is false.

A do-while(false) wrapper encloses several macro statements in one statement-like construct. The false condition makes the body execute once, while the wrapper preserves safe use after an if condition. section 10.2.1

Safe control-structure use

Define ERROR_RETURN(CODE) with a do { ... } while (false) body, then write if (a) ERROR_RETURN(x); else puts("a is 0!");. The caller's semicolon terminates the wrapper, and else remains associated with the outer if. section 10.2.1

 #define ERROR_RETURN(CODE)  \
 do {                        \
   if (CODE) return -1;      \
 } while (false)

Inspect the wrapper that turns a conditional return into a function-call-like macro. section 10.2.1

The pattern avoids the dangling-else and related statement-boundary problems caused by exposing multiple replacement statements. It remains an ugly technique, so use it deliberately rather than hiding surprising control flow. section 10.2.1

A generic SWAP macro uses the artificial loop as an outer hull, alongside single-evaluation temporaries and type checks. The wrapper supplies function-like syntax, not function semantics. section 18.3.1

 #define SWAP(X, Y)                                              \
   do {                                                          \
     /* These two variables have the role of function            \
        parameters. They ensure to evaluate the                  \
        expression X and Y once, since these could be            \
        complicated lvalue expressions with evaluated            \
        subexpressions that have side effects. */                \
     auto const swap_p1 = &(X);                                  \
     auto const swap_p2 = &(Y);                                  \
     static_assert_compatible(*swap_p1, *swap_p2,                \
                              "to exchange values, '"           \
                              #X "' and '" #Y                   \
                              "' must have compatible types");  \
     auto swap_tmp = *swap_p1;                                   \
     *swap_p1 = *swap_p2;                                        \
     *swap_p2 = swap_tmp;                                        \
   } while (false)

Examine the wrapper as part of a larger macro design that captures arguments, checks types, and performs the swap. section 18.3.1

How Modern C, Third Edition covers it

How deep it goes
Explains expansion hazards through dangling-else examples and applies the wrapper inside a generic SWAP macro.
Examples
Demonstrates ERROR_RETURN in nested if statements and uses the wrapper as the outer hull of a generic SWAP macro.
What it assumes
Assumes familiarity with C macros, if statements, compound statements, and function-like call syntax.
What you can do after
Apply it when constructing multi-statement C macros that must remain safe after conditional statements.
How it connects
Connects macro expansion with dangling else, function-like syntax, single evaluation, type checking, and generic programming.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C, Third Edition. The section links point to the parts of the book it draws on.