为什么很多linux内核中宏#defines用do { ... } while(0)?
有很多原因:
(Dave Miller的说法):
编译器对于空语句会给出告警,这是为什么#define FOO do{ }while(0);
给定一个基本块(局部可视域),定义很多局部变量;
(Ben Collins的说法):
在条件代码中,允许定义复杂的宏。可以想像有很多行宏,如下代码:
-
#define FOO(x) /
现在,想像下面的应用:
printf("arg is %s/n", x); /
do_something_useful(x);if (blah == 2)
展开后代码为:
FOO(blah);if (blah == 2)
printf("arg is %s/n", blah);
do_something_useful(blah);; - 就像你看到的,if仅仅包含了printf(),而do_something_useful()调用是无条件调用。因此,如果用do { ... } while(0),结果是:
-
if (blah == 2)
do {
printf("arg is %s/n", blah);
do_something_useful(blah);
} while (0); - 这才是所期望的结果。
- (Per Persson的说法):
- 像 Miller and Collins指出的那样,需要一个块语句包含多个代码行和声明局部变量。但是,本质如下面例子代码:
-
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
- 上面代码在有些时候却不能有效工作,下面代码是一个有两个分支的if语句:
-
if (x > y)
exch(x,y); // Branch 1
else
do_something(); // Branch 2 - 展开后代码如下:
-
if (x > y) { // Single-branch if-statement!!!
int tmp; // The one and only branch consists
tmp = x; // of the block.
x = y;
y = tmp;
}
; // empty statement
else // ERROR!!! "parse error before else"
do_something(); - 问题是分号(;)出现在块后面。解决这个问题可以用do{}while(0):
-
if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while(0);
else
do_something();