Do{...}while(0)

Posted by 大雁小鱼的博客 on June 10, 2018

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(); \  
})