do while(0)在宏定义的妙用

    do{
        
        //do something

    ]while(0);

上面是一段使用 do while(0) 的代码,显然如上代码只会执行一次,这样使用显然是毫无意义的的(当然莫种情况下还是有意义的,比如在里面定义局部变量),所以在常规的代码编写中,我们并不会使用 do while(0) 这种结构。但是在Linux内核代码中却大量使用了do while(0) 这种结构:

图1 内核代码搜索while(0)结果截图

那么,通常在什么时候使用呢,随便点击一个查看(其实其他都是同种类型):

图2 内核源码中do while(0)使用例子

细看,这居然是一个宏,(作为小白,平时的宏都是一行的),其实像这样复杂的宏,在内核源码中非常常用,可以使代码更加简洁,也不会像函数那样降低代码运行速度。那么为什么要使用 do while(0) 呢,我们使用一下例子分析:

例如我有这样一个宏:

void fun1(){
	printf("fun1\n");
}
void fun2(){
	printf("fun2\n");
}

#define ifTrue	fun1(); fun2();        //复杂宏

那么如果我有一下这样的应用:

#define ifTrue	fun1(); fun2();

if(flag)            
   ifTrue;

预编译展开宏之后:

#define ifTrue	fun1(); fun2();

if(flag)           
   fun1(); 
   fun2();

那么就会出现一个问题,无论flag是什么值 fun2() 都会被执行。程序逻辑就会错误。

所以有同学就说了,加个大括号不就行了吗?就像这样:

#define ifTrue	{fun1(); fun2();}        //复杂宏

那么,程序预编译展开宏之后将是这样:

#define ifTrue	{fun1(); fun2();}

if(flag)           
   {fun1(); fun2();};
   

后面将多出一个分号(单独的分号代表空语句),对于现在9102的编译器当然没问题,但是对于旧编译器可能就会出现警告甚至是错误。怎么去将宏统一又能消化掉后面的分号呢,do while(0) 结构就很好的解决了上面的所有烦恼,do while() 设计的初心应该是循环控制结构,但是却被挖掘出另一种用途,这就是程序设计之美!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章