A compound expression is a compiler extension written ({ ... }). It groups statements and expressions into one expression whose value is the final expression, such as (void)0. Unlike a do { ... } while (false) macro, it can appear where an expression is required and can return a value. section 18.4
A value-producing macro
#define MAX_EQSIGN(X, Y) \ ({ \ auto const max_x = (X); \ auto const max_y = (Y); \ (max_x < max_y) ? max_y : max_x; \ }) The final conditional expression supplies the compound expression's value. Capturing X and Y first also evaluates each argument once. section 18.4
Important constraints and behavior:
- The construct is offered by GCC and related compilers; C23 does not provide a general equivalent. section 18.4
- Identifiers declared inside remain exposed to surrounding scopes, and goto statements and labels can jump into or out of the construct. section 18.4
#define SWAP(X, Y) \
/* This starts the compound expression construct. */ \
({ \
/* 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; \
/* ensure that the type of the expression is void */ \
(void)0; \
})
Annotated SWAP expansion showing compound-expression syntax, single evaluation of arguments, type checking, and the final expression value. section 18.4
