转载自: http://www.cnblogs.com/charlesblc/p/6080315.html
在开源软件里面经常可以看到这样的写法。
#define X(a) do { f1(a); f2(a); } while(0)
1. 主要作用是放在宏定义里面,避免宏带来的语法问题。
比如
#define DOSOMETHING()\
cmd1;\
cmd2;
而调用的时候
if(a>0)
DOSOMETHING(); 会有问题,需要用到上面提到的
而这时候,为什么不用 if (1) { ... } 呢?
有两方面原因:
首先,会多出不必要的分号,比如:
if (1)
my_code;
另外更重要的是,有if-else的问题:
if (1)
my_code;
else { ... }
当然了,如果定义成
#define X(a) if(1) { f1(a); f2(a); } else{}
就和下面的 do...while(0)一样安全了。但是上面的if-else写法不需要写分号;,有利有弊。
#define X(a) do { f1(a); f2(a); } while(0)
2. 还有一个重要原因是,可以用来取代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)和break的配合,写成:
int foo()
{
somestruct* ptr = malloc(...);
do{
dosomething...;
if(error)
{
break;
}
dosomething...;
if(error)
{
break;
}
dosomething...;
}while(0);
free(ptr);
return 0;
}
goto转换为do...while+break,在程序结构上、编译优化上,都有很多好处。我觉得。
3. 避免空宏引起的warning
内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏:
#define EMPTYMICRO do{}while(0)
我觉得,这个也可以用if-else来代替。
4. 定义一个单独的函数块来实现复杂的操作,避免作用域或者命名空间冲突
当你的功能很复杂,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);,将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。