do{…}while(0)
在Linux内核的源码或者其他一些C的开源代码中(比如说Redis源码中),经常会遇见这样的代码:
do{
...
}while(0)
这种代码一看就让人觉得很奇怪,它一看就不是一个循环,似乎一点意义都没有,那么为什么要这样使用呢?实际上这里头的学问还真的挺大的,这种写法的主要目的是为了定义复杂的宏,同时避免使用的时候出现错误。
举例来说,假设你需要定义这样的一个宏:
#define DOSOMETHING()\
foo1();\
foo2();
这个宏的意思是,当调用DOSOMETHING时,函数foo1和函数foo2都会被调用到,但是在某些场景下它是有问题的,比如你这么写:
if(a>0)
DOSOMETHING();
宏在处理的时候是直接展开的,你实际上写的代码是这个样子的:
if(a>0)
foo1();
foo2();
这与你的本意相悖,因为无论a是否大于0,foo2都会被执行。 于是有人就想到了使用do{…}while(0)的写法,其目的是使得do里面的代码只执行一次:
#define DOSOMETHING() \
do{ \
foo1();\
foo2();\
}while(0)\
...
if(a>0)
DOSOMETHING();
...
这样,当宏被展开的时候,就不会出错。GCC提供Statement-Expressions用以替代do{…}while(0); 所以也可以这样定义:
#define DOSOMETHING() ({\
foo1(); \
foo2(); \
})