從而不會與上下文發生混淆。同時因爲絕大多數的編譯器都能夠識別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; /
})