【轉】linux中do{...} while(0)的解釋


  在看ldlm的代碼過程中遇到了一個很奇怪的問題,有很多宏定義使用了do while(0)這種看起來好像沒啥用的代碼。然后我就問問師兄,才得知,這種用法很常見,自己又查了一下資料,原來在linux內核代碼中經常用到這個東西!現在就將這個東西整理一下。

        

為什么在內核中碰到很多  #define ...  do{...} while(0) ?

有以下幾點原因:

1、空語句在編譯的時候會出現警告,所以有必要用#define FOO do{ } while(0)

2、給定一個基本塊,可以在里面定義局部變量

3、為了能夠在條件語句中使用復雜的宏定義。例如下面這段代碼:

     #define FOO(x) \

     printf("arg is %s\n", x); \

     do_something_useful(x);

      如果這樣用:

      if (blah == 2)

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

這是我們所期望的。

 

如果你希望定義一個包含多行語句和一些局部變量的時候. 一般的定義方式只能這樣:

  #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) {                // 單分支if

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  }

  ;                           // 空語句

  else                        // 錯誤!!! "parse error before else"

  do_something();

  問題是由於在語句塊后直接加入分號(;)引起的. 解決辦法是將語句塊放入 do 和 while (0)中間.這樣就得到了一條單語句, 而不是被編譯器判斷為語句塊.現在的if語句如下:

  if (x > y)

  do {

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  } while(0);

  else

  do_something();

 

 

假設有這樣一個宏定義  
 
#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)這種無用的循環並進行優化,所以使用這種方法也不會導致程序的性能降低。  

 

參考資料

http://blog.csdn.net/chenhu_doc/article/details/856468

http://www.233.com/linux/fudao/20101102/140715235.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM