do { ... } while(0)看似是一种多余的写法,但是在Linux下却经常可以看到。这是因为当宏定义采用一条语句代替多条语句时,采用do { ... } while(0)可以防止意想不到的语法错误。
例如:
#define foo \
statementA; \
statementB
当宏替换如下代码时:
if (condition)
foo;
得到:
if (condition)
statementA;
statemetnB;
这与实际期待的代码不符。
如果采用语句块的方式,如:
#define foo \
{statementA; \
statementB;}
当宏替换如下if-else代码时:
if (condition)
foo;
else
statementC;
得到:
if (condition)
{statementA;
statementB;}; // 这里最后的分号导致了语法错误
else
statementC;
为了解决这个问题,不能在foo之后跟上分号,即:
if (condition)
foo
else
statementC;
尽管这样可以得到正确的代码,但是这样做是很不自然的。
因此,我们采用do while(0)的方式进行宏定义:
#define foo \
do { \
statementA; \
statementB; \
} while(0)
宏替换上述if-else代码:
if (condition)
foo;
else
statementC;
得到:
if (condition)
do {
statementA;
statementB;
}while(0);
else
statementC;
由此得到了可以正确执行的代码。
由于while(0),循环条件不成立,do while(0)严格执行一次。同时由于循环条件为常量0,编译器不会生成循环代码而增加循环开销。
参考:
http://www.bruceblinn.com/linuxinfo/DoWhile.html
http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we-define-a-macro