c++ - do{}while(0) 的作用
ringa_lee
ringa_lee 2017-04-17 11:27:56
0
5
569

在 cocos2d-x 源码 中,有大量的这种 do{}while(0) 的用法,例如这个:

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

根据语意,这样写至少保证do后面的代码块执行一次。

这样写的意义是什么?为什么不直接使用块,而一定要加上 do while 循环?

ringa_lee
ringa_lee

ringa_lee

全部回覆(5)
洪涛

發現這個問題一搜一大堆哦,題主確定不是SF的托麼,哈哈,開個玩笑

  1. 有時候只是為了程式碼分塊,比僅僅使用{}更直觀些。
  2. 當你執行一段程式碼到一半,想跳過剩下的一半的時候,如果你正處於do while循環中,則能用break達到這個目的。
  3. 變形的goto,有些公司不讓用goto
  4. 這樣做也可以是兼容各種編譯器。
  5. 為了展開的時候不會出錯。如果直接放在花括号裡會出錯的

這篇文章很詳細

大家讲道理

do while(0) 還有個用的地方是在巨集定義#define裡

不加大括號的程式碼

#include <stdio.h>

#define foo(x) int a = x;int b = x;

int main()
{
    int i = 0;
    if (i == 0)
        //无法编译,缺少大括号
        foo(2);
    else
        i = 1;
    return 0;
}

加了大括號的程式碼

#include <stdio.h>

//加上大括号
#define foo(x) {int a = x;int b = x;}

int main()
{
    int i = 0;
    if (i == 0)
        //无法编译,后面多了个;号,得把;去了才能编译的过去,和C的语法不怎么协调
        foo(2);
    else
        i = 1;
    return 0;
}

do while(0)的程式碼

#include <stdio.h>

#define foo(x) do {int a = x;int b = x;} while(0)

int main()
{
    int i = 0;
    if (i == 0)
        //这下舒服了 xD
        foo(2);
    else
        i = 1;
}
洪涛

區塊級作用域。避免 {} 區塊裡面的變數名稱擴散到上層作用域。好處是減少外層作用域中需要記憶的名字的數量,減少誤用這些變數的可能性。

具體來說,這段程式碼中 pImage 就被限制在只能在這個區塊中使用,出了這個區塊就不能用了,避免程式設計師誤用,也避免名字衝突。

在 C++ / Java 等支援區塊級作用域的語言中常見。 gcc 也支援只寫大括號:

{
    int x = 0;
    // do something
}
// can't use x here
{
    int x = 1; // another x
    // do something
}
// can't use x here
大家讲道理

另外一種作用是這樣的使用goto來統一錯誤處理,如:

bool foo()
{
    int a, b, c;
    bool ok;
    ok = bar1(&a);
    if (!ok)
        goto failed;
    ok = bar2(&a);
    if (!ok)
        goto failed;
failed:
    process_error();
    return false;
exit:    
    return true;
}

如果配合do{}while(0)的話.會這樣的

bool foo()
{
    int a, b, c;
    bool ok = true;
    do
    {  
        ok = bar1(&a);
        if(!ok)
            break;
        ok = bar2(&b);
        if(!ok)
            break;
    } while(0);
    if (!ok)
    {
        process_error();
        return false;
    }
    else
    {
        return true;
    }
}
巴扎黑

在巨集中常用do-while, 例如

#define SAFE_FREE(p) do {free(p);p=NULL;} while(0)

在程式碼裡呼叫這個巨集:

SAFE_FREE(ptr);

用do-while, 上面的宏呼叫可以看起來像"函數呼叫", 句尾可以有分號
因為do{} while(0); 最後可以帶分號, 並且利用大括號把語句括起來;

加入不用do-while, 上面的宏就寫成:

define SAFE_FREE(p)   free(p);p=NULL;

呼叫的時候一般人會這麼用:

if(条件)
 SAFE_FREE(p); // 展开后, p=NULL就不在if控制内了
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板