zz:do{}while(0)的意義

csdn's FAQ:ide

一直覺得Linux裏面,那些do{}while(0)只是爲了程序的源代碼看起來比較好看而已  
今天據說他是有特殊做用的,在線請教,是什麼做用?  
---------------------------------------------------------------  
 
是爲了解決使用宏的時候煩人的分號問題。  
---------------------------------------------------------------  
 
樓說的不是很全面,我給個例子吧  
 
#define  wait_event(wq,condition)  /  
 
do{  if(condition)  break;  __wait_event(wq,condition);  }while(0)  
 
這是一個奇怪的循環,它根本就只會運行一次,爲何不去掉外面的do{..}while結構呢?我曾一度在內心把它叫作「怪圈」。原來這也是很是巧妙的技巧。在工程中可能常常會引發麻煩,而上面的定義可以保證這些麻煩不會出現。下面是解釋:  
 
假設有這樣一個宏定義  
 
#define  macro(condition)  if(condition)  dosomething();  
 
如今在程序中這樣使用這個宏:  
 
if(temp)  
             macro(i);  
else  
             doanotherthing();  
 
一切看起來很正常,可是仔細想一想。這個宏會展開成:  
 
if(temp)  
             if(condition)  dosomething();  
else    
             doanotherthing();  
 
這時的else不是與第一個if語句匹配,而是錯誤的與第二個if語句進行了匹配,編譯經過了,可是運行的結果必定是錯誤的。  
 
爲了不這個錯誤,咱們使用do{….}while(0)  把它包裹起來,成爲一個獨立的語法單元,從而不會與上下文發生混淆。同時由於絕大多數的編譯器都可以識別do{…}while(0)這種無用的循環並進行優化,因此使用這種方法也不會致使程序的性能下降。  
 
---------------------------------------------------------------  
 
但是直接用{}括起來的話,最後的分號會引發麻煩的  
---------------------------------------------------------------  
 
但這樣就必定要在最後加分號,不能看成表達式用了。  
唉,仍是儘可能避免用宏替換的方法,太容易出現問題了。性能

**************************************************************** 優化

FAQ FROM CSDN:this

FAQ/DoWhile0

Why do a lot of #defines in the kernel use do { ... } while(0)?spa

There are a couple of reasons:code

  • (from Dave Miller) Empty statements give a warning from the compiler so this is why you see #define FOO do { } while(0).orm

  • (from Dave Miller) It gives you a basic block in which to declare local variables.get

  • (from Ben Collins) It allows you to use more complex macros in conditional code. Imagine a macro of several lines of code like:編譯器

    #define FOO(x) /         printf("arg is %s/n", x); /         do_something_useful(x);

    Now imagine using it like:it

    if (blah == 2)         FOO(blah);

    This interprets to:

    if (blah == 2)         printf("arg is %s/n", blah);         do_something_useful(blah);;

    As you can see, the if then only encompasses the printf(), and the do_something_useful() call is unconditional (not within the scope of the if), like you wanted it. So, by using a block likedo { ... } while(0), you would get this:

    if (blah == 2)         do {                 printf("arg is %s/n", blah);                 do_something_useful(blah);         } while (0);

    Which is exactly what you want.

  • (from Per Persson) As both Miller and Collins point out, you want a block statement so you can have several lines of code and declare local variables. But then the natural thing would be to just use for example:

    #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

    However that wouldn't work in some cases. The following code is meant to be an if-statement with two branches:

    if (x > y)         exch(x,y);          // Branch 1 else           do_something();     // Branch 2

    But it would be interpreted as an if-statement with only one branch:

    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();

    The problem is the semi-colon (;) coming directly after the block. The solution for this is to sandwich the block between do and while (0). Then we have a single statement with the capabilities of a block, but not considered as being a block statement by the compiler. Our if-statement now becomes:

    if (x > y)         do {                 int tmp;                 tmp = x;                 x = y;                 y = tmp;         } while(0); else         do_something();
相關文章
相關標籤/搜索