你用過do{...}while(0)嗎?

當第一次遇到do{...}while(0),我是懵的,這是什麼操作,爲了好看嗎?後來發現Linux內核中隨處可見啊,大神們這樣的操作肯定是有道理的。查詢了一些資料,做一下總結。在今後C語言開發中,你也可以放心使用這一技巧。

1. 配合定義複雜的宏,避免宏在預處理展開時出錯

舉個例子,假設你定義了一個宏:

#define DOSOMETHING() fuc1(); fuc2();

當調用DOSOMETHING()的時候,你希望調用fuc1()和fuc2()來做一些事情。但是當在if語句中調用時,可能會這麼寫:

if(num > 0)
    DOSOMETHING();

預處理展開宏,替換文本如下:

if(num > 0)
    fuc1();
fuc2();

這樣就出現了問題,fuc2()就不受if語句的控制了,導致程序出錯。

可能你會說,宏定義建議把整個表達式用大括號括起來的:

#define DOSOMETHING() {fuc1(); fuc2();}

還是if語句來調用:

if(num > 0)
    DOSOMETHING();
else
    printf("num<0\r\n");

這樣程序編譯會報錯:

我們查看預處理文件,宏展開是這樣子的:

if語句被後面的分號提前結束,else無法與其匹配。而使用do{...}while(0)後就不會出錯了,Linux內核中的宏定義很多都是這麼用的:

2. 避免定義空的宏時引起warning

一些大型的C工程中,爲了兼容不同的架構,或者爲了移植方便,都會用到空的宏定義。在編譯的時候,編譯器會給出警告,爲了避免這些warning,我們可以使用do{...}while(0)來定義空的宏:

3. 避免goto語句

在一些函數中,我們可能需要在return語句之前做一些清理工作,很多人不提倡用goto語句。好吧,do{...}while(0)可以實現同樣的功能:

int foo()
{
    somestruct *ptr = malloc(...);
    do
    {
        dosomething...;
        if(error)
            break;
        dosomething...;
        if(error)
            break;
        dosomething...;
    }
    while(0);

    free(ptr);
    return 0;
}

代碼可讀性和可維護性要比goto語句好多了。

4. 定義單一的函數塊來完成複雜的操作

當你的功能複雜,變量很多又不願增加一個函數的時候,可以將你的代碼用do{...}while(0)包裹,在裏面可以定義變量而不用考慮變量名會同函數前後重複。當然,爲了後續維護方便,不建議這麼做。

5. 就是感覺美觀好看

對,就是覺得好看,不解釋:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章