1、背景
最近再看一个开源代码的时候,看到很多宏经常这么写的:
#define XXX do{\
...\
}while()
一眼看到的时候就知道这一份代码执行一次,那么do...while还有什么意义呢?在查阅了很多资料之后,才发现,do...while(0)用处太多了,所以在这里总结一下。
2、总结
2.1 辅助定义多语句宏
如果我们定义下列宏:
#define DOSOMETHING()\
foo1();\
foo2();
这个宏的本意是,如果调用DOSOMETHING(),那么就执行foo1()和foo2(),但是如果你这么写:
if(xxx)
DOSOMETHING();
那么展开以后:
if(xxx)
foo1();
foo2();
不管条件是否满足,foo2()都会执行,那么程序逻辑与本意是不同的。如果采用do..while(0)则可以避免这个问题:
#define DOSOMETHING() \
do{ \
foo1();\
foo2();\
}while() if(a>)
DOSOMETHING();
...
2.2 避免使用goto
有些函数中,在函数return之前我们经常会进行一些收尾的工作,比如free掉一块函数开始malloc的内存,goto一直都是一个比较简便的方法。
int foo()
{
somestruct* ptr = malloc(...); dosomething...;
if(error)
{
goto END;
} dosomething...;
if(error)
{
goto END;
}
dosomething...; END:
free(ptr);
return ;
}
由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以很多人都不倡导使用,那这个时候就可以用do{}while(0)来进行统一的管理。
int foo()
{ somestruct* ptr = malloc(...); do{
dosomething...;
if(error)
{
break;
} dosomething...;
if(error)
{
break;
}
dosomething...;
}while(); free(ptr);
return ;
}
这里将函数主体使用do()while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。
2.3 避免空宏引起的warning
内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏。
#define EMPTYMICRO do{}while(0)