do{}while(0)有时可以方便地解决一些问题

辅助定义复杂宏,避免引用时出错

看下面这个宏:

#define DO_SOME_WORK() \
    func1(); \
    func2();

本意是通过调用 DO_SOME_WORK() ,来执行 func1() 和 func2() 两个函数。 按照我们习惯的调用方法:

if ( a > 0 )
    DO_SOME_WORK();

实际上展开后是:

if ( a > 0 )
    func1();
func2();

显示不符合我们的预期,如果我们在宏定义时加上 {...} 呢?也是不行,这样展开会是:

if ( a > 0 ) {
   func1();
   func2();
}

这时 do{...}while(0) 就派上用场了:

#define DO_SOME_WORK() \
do { \
    func1(); \
    func2(); \
} while (0)

避免使用 goto

有时我们会想要在函数内部做些收尾工作,比如说我们在创建一个线程池时,需要多次分配内存的操作,任何一次失败我们都希望 goto 到一个统一的释放已分配内存的任务。 但是 goto 不符合软件工程的结构化,且会破坏指令流水线的效率,所以不提倡使用,这时可以用 go{...}while(0) 配合 break 来实现目的。 下面是一个例子: 使用 goto :

int foo()
{
    somestruct* ptr = malloc(...);
    dosomething...;
    if(error)
    {
            goto END;
    }
    dosomething...;
    if(error)
    {
        goto END;
    }
    dosomething...;

END:
    free(ptr);
    return 0;
}

使用 do{...}while(0)

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

其思想就是用 do{...}while(0) 将函数主体包围起来,用 break 代替 goto,原有的收尾工作放在“循环”外。

定义空宏

有些平台上不允许定义空宏,这是可以这样做:

#define EMPTYMACRO do{}while(0)