do…while(0)的用法
这样的宏见过么:
Cpp代码:
#define FOO(x) do {\
some_code_line_1;\
some_code_line_2;\
} while (0)
(注意while(0)后面没有分号)
乍一看这个宏不过就是定义了个包含多个语句的local scope,用do…while(0)包围起来简直多此一举。直接这样不就好了么:
Cpp代码:
#define FOO(x) {\
some_code_line_1;\
some_code_line_2;\
}
但问题是这两者不等价
关键问题是前者定义出来的宏是一个非复合语句,而后者是一个复合语句。C/C++里有些语法结构对复合/非复合语句之间的区别是敏感的,例如说:
Cpp代码:
if ( someCond )
FOO(x);
else
//…
要是FOO(x)展开后是一个复合语句,那么FOO(x)后面的分号“;”就会终结整个if语句,导致else子句孤立而出现编译错误。
所以关键是那个while(0)后面不加分号。如果加了分号的话就没意义了。
如果用复合语句版本的宏,就要记得不写那个分号:
CPP代码:
if ( someCond )
FOO(x)
else
//…
但是这样与一般的函数调用风格不统一,所以很多人倾向于使用do…while(0)这个trick来把local scope包起来而不是直接用复合语句({…})。
do…while(false)的妙用
经常会遇到这样的情况,一大段代码,中间遇到某种情况,比如someObj == null,需要跳出这段代码,但是又不在循环之中,只好处理成这样:
if(someObj != null)
最后造成一大堆括号,写起来不舒服,可读性也很差。
巧用do…while(false)可以解决这个问题
do
{
if(something)
break;
foo();
}while(false);