dowhile(0)⽤法(转)
#define MACRO_NAME(para) do{macro content}while(0)
的格式,总结了以下⼏个原因:
1,空的宏定义避免warning:
#define foo() do{}while(0)
2,存在⼀个独⽴的block,可以⽤来进⾏变量定义,进⾏⽐较复杂的实现。
3,如果出现在判断语句过后的宏,这样可以保证作为⼀个整体来是实现:
#define foo(x) /
action1(); /
action2();
在以下情况下:
if(NULL == pPointer)
foo();
就会出现action1和action2不会同时被执⾏的情况,⽽这显然不是程序设计的⽬的。
4,以上的第3种情况⽤单独的{}也可以实现,但是为什么⼀定要⼀个do{}while(0)呢,看以下代码:
#define switch(x,y) {int tmp; tmp=x;x=y;y=tmp;}
if(x>y)
switch(x,y);
typeof的用法else        //error, parse error before else
otheraction();
在把宏引⼊代码中,会多出⼀个分号,从⽽会报错。
//------------------------------------------------
使⽤do{….}while(0) 把它包裹起来,成为⼀个独⽴的语法单元,
从⽽不会与上下⽂发⽣混淆。同时因为绝⼤多数的编译器都能够识别do{…}while(0)这种⽆
⽤的循环并进⾏优化,所以使⽤这种⽅法也不会导致程序的性能降低。为什么很多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();
( Bart Trojanowski的说法):
Gcc加⼊了语句解释,它提供了⼀个替代do-while-0块的⽅法。对于上⾯的解决⽅法如下,并且更加符合常理
#define FOO(arg) ({ /
typeof(arg) lcl; /
lcl = bar(arg);    /
lcl;              /
})

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。