C multi-line macro: do/while(0) vs scope block [duplicate]
Andrey Tarasevich provides the following explanation:
[Minor changes to formatting made. Parenthetical annotations added in square brackets []
].
The whole idea of using 'do/while' version is to make a macro which willexpand into a regular statement, not into a compound statement. This isdone in order to make the use of function-style macros uniform with theuse of ordinary functions in all contexts.
Consider the following code sketch:
if (<condition>) foo(a);else bar(a);
where
foo
andbar
are ordinary functions. Now imagine that you'dlike to replace functionfoo
with a macro of the above nature [namedCALL_FUNCS
]:
if (<condition>) CALL_FUNCS(a);else bar(a);
Now, if your macro is defined in accordance with the second approach(just
{
and}
) the code will no longer compile, because the 'true'branch ofif
is now represented by a compound statement. And when youput a;
after this compound statement, you finished the wholeif
statement, thus orphaning theelse
branch (hence the compilation error).One way to correct this problem is to remember not to put
;
aftermacro "invocations":
if (<condition>) CALL_FUNCS(a)else bar(a);
This will compile and work as expected, but this is not uniform. Themore elegant solution is to make sure that macro expand into a regularstatement, not into a compound one. One way to achieve that is to definethe macro as follows:
#define CALL_FUNCS(x) \do { \ func1(x); \ func2(x); \ func3(x); \} while (0)
Now this code:
if (<condition>) CALL_FUNCS(a);else bar(a);
will compile without any problems.
However, note the small but important difference between my definitionof
CALL_FUNCS
and the first version in your message. I didn't put a;
after} while (0)
. Putting a;
at the end of that definitionwould immediately defeat the entire point of using 'do/while' and makethat macro pretty much equivalent to the compound-statement version.I don't know why the author of the code you quoted in your originalmessage put this
;
afterwhile (0)
. In this form both variants areequivalent. The whole idea behind using 'do/while' version is not toinclude this final;
into the macro (for the reasons that I explainedabove).