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)