Possible Duplicates:
What’s the use of do while(0) when we define a macro?
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
do { … } while (0) what is it good for?
I've seen some multi-line C macros that are wrapped inside a do/while(0) loop like:
#define FOO \
do { \
do_stuff_here \
do_more_stuff \
} while (0)
What are the benefits (if any) of writing the code that way as opposed to using a basic block:
#define FOO \
{ \
do_stuff_here \
do_more_stuff \
}
1 Answer 1
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 will expand into a regular statement, not into a compound statement. This is done in order to make the use of function-style macros uniform with the use of ordinary functions in all contexts.
Consider the following code sketch:
if (<condition>) foo(a); else bar(a);where
fooandbarare ordinary functions. Now imagine that you'd like to replace functionfoowith 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 ofifis now represented by a compound statement. And when you put a;after this compound statement, you finished the wholeifstatement, thus orphaning theelsebranch (hence the compilation error).One way to correct this problem is to remember not to put
;after macro "invocations":if (<condition>) CALL_FUNCS(a) else bar(a);This will compile and work as expected, but this is not uniform. The more elegant solution is to make sure that macro expand into a regular statement, not into a compound one. One way to achieve that is to define the 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 definition of
CALL_FUNCSand the first version in your message. I didn't put a;after} while (0). Putting a;at the end of that definition would immediately defeat the entire point of using 'do/while' and make that macro pretty much equivalent to the compound-statement version.I don't know why the author of the code you quoted in your original message put this
;afterwhile (0). In this form both variants are equivalent. The whole idea behind using 'do/while' version is not to include this final;into the macro (for the reasons that I explained above).
2 Comments
comp.lang.c. bytes.com apparently "appropriates" the content of comp.lang.c without making any references to the source.
({...})construct is a GCC extension and is not supported by ISO standard C.