优美的代码:do...while(0)

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)
上一篇:MVC 传值


下一篇:jQuery轮播