看代码经常会发现有些宏定义, 代码体用 do{}while(0)语句包起来.
宏在编译前就会展开成代码, 而且展开方式就是赤裸裸的文本替换方式.所以边界控制不好容易出问题. 当然最好是使用inline替换宏函数或者const替换宏的常量定义,这俩有类型检查更安全.
说回do{}while(0),记录一下目前知晓的两个原因:
1 宏内的多段代码可以在任何情况下 只有一种执行方式
#define func(x) f1(x); f2(x)
//若正常调用 确实是没问题, 如下
func(x);
//等价于
f1(x);
f2(x);
//但是假如
if(condition)
func(x);
//就会变为
if(condition)
f1(x);
f2(x);
//当然这个写法是不规范的,正常if后面要加括号的,这里就不讨论了, 只能说有使用错误的可能性,作为一个代码编写者,应尽可能提供给用户不易使用出错的代码.
//如果是do{f1(x); f2(x);}while(0)
//上面出错代码就会变为
if(condition)
do
{
f1(x);
f2(x);
}
while(0);
// 其实就变成了一个括号
若直接在 宏定义的时候 把花括号写上, 也有的时候不太行
2.宏不用额外加括号,可以避免一些使用上的错误
#define func(x) { f1(x); f2(x); }
// 若 if else方式调用
if (!condition)
func(x);
else
func(x);
// 等价于
if (!condition)
{
f1(x); f2(x);
}; // 这里多了个分号 , 编不过去了
else
{
f1(x); f2(x);
};
// 分号语法错误了
do while这种写法, 使得代码的使用者 可以更正确地使用我们写的宏