The whole idea behind this trick is to find a way to create a multi-line (i.e compound) statement that also incorporates a terminating ;
as its integral part. That will give you the opportunity to use ;
after your macro invocation without inadvertently introducing an empty statement.
The ordinary compound statement in { ... }
doesn't work because it does not end in ;
. The only multi-line statement in C/C++ that ends in ;
is do/while
. There's no other statements in C/C++ grammar that would satisfy this requirement. (This is an inaccurate claim, see my "P.S." below)
In all other cases (including your if (1) {...}
) the ;
after the macro invocation will be seen as an additional independent standalone empty statement. This will make it impossible to write a ;
after your macro invocation when it is used in contexts requiring exactly one statement (like true branch of if-else
or the body of do/while
cycle).
For example, if you define
#define A() if (1) {}
then this code will not compile
do
A();
while (1);
because it will be replaced with
do
if (1) {}; /* <- two statements, not one */
while (1);
and that is actually two statements between do
and while
. Specifying two statements between do
and while
without wrapping them into {}
is syntax error.
P.S. Correction: The claim I make above about do/while
being the only viable variant is incorrect . In @Michael Burr's answer you can see another suitable variant, which is using the else ((void) 0)
trick for the same purpose. However, the main principle remains the same.