FAQ/DoWhile0
为什么内核代码中大量的宏定义#define都使用do{...} while(0)?
有如下几个原因:
- (from Dave Miller) 对于空语句,编译器会报警告,这也就是你为什么常会看到#define FOO do{}while(0)
- (from Dave Miller) 可以在宏定义基本块中声明局部变量
- (from 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()调用并没有包含在if语句的作用域
之中,即do_something_useful()语句将会无条件执行,而这并不是我们所期望的。因此,通过使用宏定义像do
{...}while(0)这样的代码块,我们将得到
if (blah == 2)
do {
printf("arg is %s\n", blah);
do_something_useful(blah);
} while (0);
|
上述宏定义扩展,也正是我们所需要的。
- (from Per Persson) 正如Miller和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语句将仅包含一个分支:
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();
|
事实上,问题就出在if第一个分支代码块后的紧跟着的分号;。解决之道可以将宏定义块置于do和while(0)之
间。如此我们便拥有了一个单一的语句,但它却起着代码块的作用,而且编译器也不会将其作为代码块。于是
我们的if语句现在变为
if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while(0);
else
do_something();
|
- (from Bart Trojanowski) gcc增加了”语句-表达式“,它可以用于替代do-while-0方式,并且使用起来更为清楚简洁些。
#define FOO(arg) ({ \
typeof(arg) lcl; \
lcl = bar(arg); \
lcl; \
})
|
阅读(1389) | 评论(1) | 转发(0) |