中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解C語言do{}while(0)結構

發布時間:2021-11-01 14:27:15 來源:億速云 閱讀:323 作者:iii 欄目:編程語言

這篇文章主要介紹“怎么理解C語言do{}while(0)結構”,在日常操作中,相信很多人在怎么理解C語言do{}while(0)結構問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解C語言do{}while(0)結構”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

在嵌入式開發中,宏定義非常強大也非常便捷,如果正確使用可以讓你的工作事半功倍。然而,在很多的C程序中,你可能會看到不是那么直接的比較特殊一點的宏定義,比如do{}while(0)。

do{conditional code}while(condition)結構

一般結構如以下代碼

do  {    //循環體  }  while (條件表達式);

do while/while do的區別

  •  do while()

意思是先干了再說!!

  •  while() do

意思是先看看能不能干!

初見do{...}while(0)

linux內核和其他一些開源的代碼中,經常會遇到這樣的代碼:

do{   ...  }while(0)

這樣的代碼一看就不是一個循環,do..while表面上在這里一點意義都沒有,只執行一次而已,那么為什么要這么用呢?

總結了7種妙處

實際上,do{...}while(0)的作用可不止一點點,下面我列舉了一些。

  1.  有時候只是為了代碼分塊,比僅僅使用{}更直觀些。例如在cocos2d-x代碼中 

do  {      CCImage* pImage = new CCImage();      CC_BREAK_IF(NULL == pImage);      bRet = pImage->initWithString(text, (int)dimensions.width, (int)dimensions.height, eAlign, fontName, (int)fontSize);      CC_BREAK_IF(!bRet);      bRet = initWithImage(pImage);      CC_SAFE_RELEASE(pImage);  } while (0);

    2.  為了宏展開的時候不會出錯。如果直接放在花括號里會出錯的

舉例來說,假設你需要定義這樣一個宏:

#define DOSOMETHING() action1(); action2();

這個宏的本意是,當執行DOSOMETHING()時,action1(),action2()都會被調用。如果有判斷,再執行這個宏的話,如下:

if(NULL == pPointer)    DOSOMETHING();  else    ...

這樣宏在預處理的時候會直接被展開,放在花括號里,那么實際上寫的代碼如下:

if(NULL == pPointer)      action1();  action2();  else    ...

這展開存在兩個問題:

  •  因為if分支后面有兩個語句,導致else分支沒有對應的if,編譯失敗。

  •  假設沒有else分支,則DOSOMETHING中的第二個語句無論if測試是否通過,都會執行。

那么僅僅使用{}把action1()、action2()包起來行么?比如:

#define DOSOMETHING() { action1(); action2(); }

我們在寫代碼的時候都習慣在語句右面加上分號,如果在宏中使用{},代碼編譯展開后宏就相當于這樣寫了:{...};,展開后如下:

if(NULL == pPointer)  {      action1();      action2();  };  else    ...

這段代碼中大括號后多了一個分號,如果有else,那么else又沒有對應的if了,編譯出錯。

那么辦法來了

如果我們使用do{...}while(0)來定義宏,即:

#define DOSOMETHING() \          do{ \            action1();\            action2();\          }while(0)\

宏被展開后,上面的調用語句會保留初始的語義,同時絕大部分編譯器都能夠識別do{...}while(0)這種無用的循環并進行優化,不會導致性能優化的降低。

小結

在Linux內核和驅動代碼還有cocos2d-x中,很多宏實現都使用do{...}while(0)來包裹他們的邏輯,Google的Robert Love(先前從事Linux內核開發)給我們解答如下:

  “    讓你定義的宏總是以相同的方式工作,不管在調用代碼中怎么使用分號和大括號,而該宏總能確保其行為是一致的。

    3.  當你執行一段代碼到一半,想跳過剩下的一半的時候,如果你正處于do{...}while(0)循環中,則能用break達到這個目的。

do  {    執行.    再執行…    if (如果有什么條件滿足)    {      我想跳到另外一段代碼了,剩下的不執行了,可是不建議用goto語句,怎么辦呢?       break;/*搞定*/    }    我有可能被執行.  }while(false)

舉個例子如下

do  {    if(!a) break;    //do something here    if(!b) break;    //do another thing here    }while(0);

    4.  變形的goto,有些公司不讓用goto。在一些函數中,需要實現條件轉移,或者構成循環,跳出循環體,使用goto總是一種簡單的方法,例如:

#include <stdio.h>  #include <stdlib.h>  int main()  {     char *str;     /* 最初的內存分配 */     str = (char *) malloc(15);     if(str != NULL)       goto loop;     printf("hello world\n");  loop:     printf("malloc success\n");     return(0);  }

但由于goto不符合軟件工程的結構化,而且有可能使得代碼難懂,所以很多人都不倡導使用,這個時候我們可以使用do{...}while(0)來做同樣的事情:

#include <stdio.h>  #include <stdlib.h>  int main()  {    do{        char *str;        /* 最初的內存分配 */        str = (char *) malloc(15);        if(str != NULL)         break;        printf("hello world\n");    }while(0);     printf("malloc success\n");    return(0);  }

這里將函數主體部分使用do{...}while(0)包含起來,使用break來代替goto,后續的清理工作在while之后,現在既能達到同樣的效果,而且代碼的可讀性、可維護性都要比上面的goto代碼好的多了。

    5.  可以是兼容各種編譯器

int a;  a = 10;  int b;  b = 20;

這種代碼在只支持c89的編譯器上是編譯不過去的,比如ADS 2.0。

int a;  a = 10;  do  {     int b;     b = 20;  }while(0);

    6.  避免由宏引起的警告內核中由于不同架構的限制,很多時候會用到空宏。在編譯的時候,這些空宏會給出警告,為了避免這樣的warning,我們可以使用do{...}while(0)來定義空宏:

#define DOSOMETHING() do{}while(0)

    7.  定義單一的函數塊來完成復雜的操作

如果你有一個復雜的函數,變量很多,而且你不想要增加新的函數,可以使用do{...}while(0),將你的代碼寫在里面,里面可以定義變量而不用考慮變量名會同函數之前或者之后的重復,例如

int key;  string value;  int func()  {      int key = GetKey();      string value = GetValue();      dosomething for key,value;      do{          int key;string value;          dosomething for this key,value;      }while(0);      }

到此,關于“怎么理解C語言do{}while(0)結構”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

崇义县| 来凤县| 元阳县| 桐柏县| 甘谷县| 四子王旗| 宿迁市| 改则县| 尉犁县| 寿阳县| 榆林市| 金华市| 满洲里市| 寻乌县| 嘉义县| 铁岭市| 安顺市| 左云县| 柳江县| 西城区| 安福县| 雷波县| 花莲市| 普兰店市| 屯门区| 四平市| 蛟河市| 孝昌县| 正阳县| 壤塘县| 香格里拉县| 泉州市| 扶绥县| 犍为县| 武平县| 左权县| 广平县| 大港区| 萨迦县| 瑞昌市| 和林格尔县|