可能的重复:
当我们定义宏时,do while(0)有什么用?
为什么在C/ c++宏中有时会出现毫无意义的do/while和if/else语句?
{…}而(0)它有什么好处?
我见过一些多行C宏被包装在do/while(0)循环中,比如:
#define FOO \
do { \
do_stuff_here \
do_more_stuff \
} while (0)
与使用基本块相比,以这种方式编写代码有什么好处(如果有的话):
#define FOO \
{ \
do_stuff_here \
do_more_stuff \
}
Andrey Tarasevich给出了以下解释:
谷歌组
在bytes.com上
对格式做了微小的更改。在方括号[]]中添加的括号注释。
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 foo and bar are ordinary functions. Now imagine that you'd
like to replace function foo with a macro of the above nature [named CALL_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 of if is now represented by a compound statement. And when you
put a ; after this compound statement, you finished the whole if
statement, thus orphaning the else branch (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_FUNCS and 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 ; after while (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).