一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

do{...}while(0)的用法,超詳解

 鴻蛟家平 2022-04-08

轉(zhuǎn)載原文地址:http://blog.csdn.net/majianfei1023/article/details/45246865

零.導(dǎo)引
第一次見到 do{...}while(0)是在學(xué)習(xí)libevent的時(shí)候,看到里面有很多類似

  1. #define TT_URI(want) do { \
  2. char *ret = evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)); \
  3. tt_want(ret != NULL); \
  4. tt_want(ret == url_tmp); \
  5. if (strcmp(ret,want) != 0) \
  6. TT_FAIL(("\"%s\" != \"%s\"",ret,want)); \
  7. } while(0)


當(dāng)時(shí)特別疑惑,do{...}while()不是做循環(huán)的嗎,類似for,while的語法,不過現(xiàn)實(shí)開發(fā)中,用for和while的比較多,do{...}while()比較少了,算是比較不常用的語法。
但是在這里,這樣的代碼一看就不是一個(gè)循環(huán),do..while表面上在這里一點(diǎn)意義都沒有,那么為什么要這么用呢?特別疑惑的google之,恍然大悟,原來do{...}while()還有此等妙用,看來自己還差得遠(yuǎn)啊。


總體來說,do{...}while(0)有兩種用法。

 

一.定義宏,實(shí)現(xiàn)局部作用域。

1.大家做c語言題目的時(shí)候,一道必考題就是 #define的算術(shù)運(yùn)算。
比如,我隨手寫一個(gè)最簡單的#define

  1. #define FUNC(x) x*3+4
  2. ...
  3. int result = 2 * FUNC(3);


result輸出多少?  26?錯(cuò)!
這是c語言新手一定會犯的錯(cuò)誤,至少我上大學(xué)的時(shí)候第一次看到這,我就做錯(cuò)了。
要知道這道題答案是多少,首先就要知道#define的作用。
1).#define M (a+b) 它的作用是指定標(biāo)識符M來代替表達(dá)式(a+b)。在編寫源程序時(shí),所有的(a+b)都可由M代替,而對源程序作編譯時(shí),將先由預(yù)處理程序進(jìn)行宏代換,即用(a+b)表達(dá)式去置換所有的宏名M,然后再進(jìn)行編譯。
2).c語言允許宏帶有參數(shù)。在宏定義中的參數(shù)稱為形式參數(shù),在宏調(diào)用中的參數(shù)稱為實(shí)際參數(shù)。對帶參數(shù)的宏,在調(diào)用中,不僅要宏展開,而且要用實(shí)參去代換形參。(以上兩句來自百度百科)

也就是 #define是在預(yù)處理的時(shí)候進(jìn)行直接替換!(這句話是這一節(jié)的重點(diǎn))
例如之上的展開就是.
int result = 2 * x * 3 + 4
x用實(shí)參3代替就是:
int result = 2 * 3 * 3 + 4 = 22而不是26.

 

有些人可能說,這些我都知道,這跟do{...}while(0)有什么關(guān)系。

其實(shí),我只是為了告訴你,#define使用的時(shí)候要特別小心,尤其是#define一個(gè)很復(fù)雜的邏輯的時(shí)候。

我們舉個(gè)簡單的#define的例子:

  1. void print()
  2. {
  3. cout<<"print: "<<endl;
  4. }
  5. void send()
  6. {
  7. cout <<"send: "<<endl;
  8. }
  9. #define LOG print();send();
  10. int main(){
  11. if (false)
  12. LOG
  13. cout <<"hello world"<<endl;
  14. system("pause");
  15. return 0;
  16. }


這個(gè)代碼輸出什么?理論上,if(false)里面的代碼不會被執(zhí)行,也就是LOG不會被執(zhí)行,所以只應(yīng)該打印出"hello world".

 

但是事實(shí)上:

 

納悶?

注意我上面說的一句話:

也就是 #define是在預(yù)處理的時(shí)候進(jìn)行直接替換!(這句話是這一節(jié)的重點(diǎn))

也就是說,上面的if(false)...在這里是:

  1. if (false)
  2. print();
  3. send();
  4. cout <<"hello world"<<endl;


懂了吧。

 

怎么解決了,有些人馬上想到,用{...}把#define 的值括住不就可以了。的確,在這里是可以的。

我們在寫代碼的時(shí)候都習(xí)慣在語句右面加上分號,如果在宏中使用{},我們通常會這么寫:

 

#define LOG {print();send();};

當(dāng)我們的if后面有一個(gè)else呢?

 

就變成了:

  1. if (false)
  2. {
  3. print();
  4. send();
  5. };
  6. else
  7. {
  8. cout <<"hello"<<endl;
  9. }

這樣就會因?yàn)閕f語句后面多加了個(gè);而編譯不通過。不要說你說,那我不加;那要是你開發(fā)一個(gè)大型項(xiàng)目的時(shí)候你自己也不知道你自己要不要加;了,你就會被自己給繞暈了,所以統(tǒng)一的規(guī)范很重要。

 

那么來我們的最終版本:do{...}while(0);

  1. #define LOG do{print();send();}while (0);
  2. int main(){
  3. if (false)
  4. LOG
  5. else
  6. {
  7. cout <<"hello"<<endl;
  8. }
  9. cout <<"hello world"<<endl;
  10. system("pause");
  11. return 0;
  12. }

 

 

就相當(dāng)于:

  1. if (false)
  2. do{
  3. print();
  4. send();
  5. }while (0);
  6. else
  7. {
  8. cout <<"hello"<<endl;
  9. }
  10. cout <<"hello world"<<endl;


用do{...}while(0);包裹住要操作的#define,無論你外面怎么操作,都不會影響#define的操作。妙哉妙哉啊。

 

 

三.替代goto.

  1. int dosomething()
  2. {
  3. return 0;
  4. }
  5. int clear()
  6. {
  7. }
  8. int foo()
  9. {
  10. int error = dosomething();
  11. if(error = 1)
  12. {
  13. goto END;
  14. }
  15. if(error = 2)
  16. {
  17. goto END;
  18. }
  19. END:
  20. clear();
  21. return 0;
  22. }

當(dāng)然這只是一個(gè)簡單的例子,有些人說,我可以不用goto,在每一個(gè)goto調(diào)用的地方直接,那么加一個(gè)判斷,你就要加一條clear(),萬一你漏了呢?而且正常情況下,foo里面的if有很多個(gè),你要寫很多goto,END里面的邏輯也更復(fù)雜。這樣就更要小心。

 


由于goto不符合軟件工程的結(jié)構(gòu)化,而且有可能使得代碼難懂,所以很多人都不倡導(dǎo)使用,那這個(gè)時(shí)候就可以用do{}while(0)來進(jìn)行統(tǒng)一的管理:

  1. int foo()
  2. {
  3. do
  4. {
  5. int error = dosomething();
  6. if(error = 1)
  7. {
  8. break;
  9. }
  10. if(error = 2)
  11. {
  12. break;
  13. }
  14. } while (0);
  15. clear();
  16. return 0;
  17. }

是不是看起來好看多了,而且還避免了由于錯(cuò)誤導(dǎo)致的嚴(yán)重bug(比如你在clear里面是清理內(nèi)存的操作,你忘記了寫goto,而走不到END里面)。

 

在do{...}while(0)里面,在任何地方都可以break跳出,然后繼續(xù)下面的執(zhí)行邏輯。即使你不寫break,也會在執(zhí)行完一遍do之后,while(0)不滿足,自己跳出去。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    成人精品欧美一级乱黄| 亚洲一区在线观看蜜桃| 成人精品一区二区三区在线| 欧美韩日在线观看一区| 欧美日韩亚洲国产精品| 国产又黄又猛又粗又爽的片| 中文字幕一二区在线观看| 精品国产亚洲av成人一区| 俄罗斯胖女人性生活视频| 国产日产欧美精品视频| 精品视频一区二区三区不卡| 天堂网中文字幕在线视频| 国产欧洲亚洲日产一区二区| 国产乱久久亚洲国产精品| 久久99精品日韩人妻| 日韩人妻有码一区二区| 麻豆在线观看一区二区| 国产情侣激情在线对白| 亚洲精品国产主播一区| 国产午夜精品亚洲精品国产| 亚洲男女性生活免费视频| 国产欧美日韩在线一区二区| 在线观看国产午夜福利| 中字幕一区二区三区久久蜜桃| 一区二区三区亚洲天堂| 成人综合网视频在线观看| 日韩毛片视频免费观看| 亚洲一区二区精品福利| 国产欧美日本在线播放| 国产视频福利一区二区| 久久女同精品一区二区| 国产农村妇女成人精品| 樱井知香黑人一区二区| 国产又猛又大又长又粗| 国产精品一区二区有码| 日韩精品综合福利在线观看| 黄色片国产一区二区三区| 日韩免费av一区二区三区| 亚洲一区二区三区四区性色av| 中文字幕久热精品视频在线| 日本午夜乱色视频在线观看|