2012-02-29 28 views
13

可能重複:
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?爲什麼在宏定義中使用do {} while(0)?

我遇到了類似下面的代碼:

#define ev_io_init(ev,cb,fd,events) \ 
do { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} while (0) 

我想知道爲什麼筆者使用do { } while (0)這裏。 這與這有什麼不同嗎?

#define ev_io_init(ev,cb,fd,events) { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} 

BTW:代碼是從libev,ev_local.h

回答

10

一個do{}while(0)允許您從環路突破:

do{ 
    expr1; 
    foo(); 
    if (cond) 
     break; 
    expr2; 
    goo(); 
} while (0); 

它一樣是簡單的塊{...}除了你可以在需要break聲明時打破執行。你不能在一個簡單的代碼塊中做到這一點,除非你有多個檢查,這可能會很麻煩。由於條件while(0),它仍然被執行一次。

+8

...這樣做,但請不要... – moonshadow 2012-02-29 08:50:47

+0

它減少的if-else嵌套的數量。 – shuva 2018-01-09 15:21:41

15

使用循環封裝代碼允許預處理器指令在不「破壞」if-else-constructs的情況下執行多個語句。考慮以下幾點:

#define DO_SOMETHING() a();b();c(); 

void foo() 
{ 
    // This is ok... 
    DO_SOMETHING(); 
} 

void bar() 
{ 
    // ...whereas this would trigger an error. 
    if (condition) 
     DO_SOMETHING(); 
    else 
     blah(); 
} 

第二個例子打破了的if-else-構建因爲三條語句後面是else條款。爲了使其能夠正確替代,DO_SOMETHING中的說明應附上do { ... } while(0)

+3

當然,如果你使用裸線如果這樣的行,你值得你的代碼打破... – Simon 2012-02-29 08:54:59

+2

@Simon但不linux內核編碼風格建議我們使用裸線,如果其他線路一行塊? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza 2015-11-23 03:17:50

+2

@CoderSpinoza顯然是這樣,如果我要在linux內核上工作,那麼我會遵循這種風格。在其他地方,我會避免它。 – Simon 2015-11-23 11:25:57

23

考慮if(something) function1(); else function2();

如果function1()實際上是一個宏,只是用{ }需要你省略分號在使用點,但do { } while(0)允許您使用完全相同的語法,作爲一個真正的功能。

(不使用任何類型的塊結構的所有隻會產生完全斷碼,natch)

相關問題