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

在 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

reply all(5)
洪涛

I found this question and searched a lot. Is the person who asked the question not from SF? Haha, just kidding

  1. Sometimes just for code chunking, it is more intuitive than just using {}.
  2. When you are halfway through executing a piece of code and want to skip the remaining half, if you are in a do while loop, you can use break to achieve this purpose.
  3. Deformed goto, some companies do not allow the use of goto.
  4. This can also be done with 兼容 various compilers.
  5. In order to there will be no errors when unfolding. If you put it directly in 花括号, it will be wrong

This article is very detailed

大家讲道理

Do while(0) is also useful in macro definition #define

Code without braces

#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;
}

Code with braces

#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;
}

Code of 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;
}
洪涛

Block-level scope. Avoid variable names inside {} blocks from spreading into the upper scope. The advantage is that it reduces the number of names that need to be remembered in the outer scope and reduces the possibility of misuse of these variables.

Specifically, in this code, pImage is restricted to be used only in this block, and cannot be used outside this block to avoid misuse by programmers and avoid name conflicts.

Common in languages ​​that support block-level scoping, such as C++/Java. gcc also supports writing only curly braces:

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

Another function is to use goto to unify error handling, such as:

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

If you use do{}while(0), it will look like this

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 is commonly used in macros, such as

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

Call this macro in code:

SAFE_FREE(ptr);

Using do-while, the above macro call can look like a "function call", and there can be a semicolon at the end of the sentence
Because do{} while(0); can have a semicolon at the end and use braces to enclose the statement;

Without do-while, the above macro is written as:

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

When calling, most people will use it like this:

if(条件)
 SAFE_FREE(p); // 展开后, p=NULL就不在if控制内了
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template