作者: 边城量子 ( shihezichen@live.cn )
背景
在阅读C++库的代码过程中,经常会遇到把一个宏定义用 do{ }while(false) 包括起来的情况, 例如 Sophus 库中 common.hpp 就有如下代码:
common.hpp:
#define SOPHUS_ENSURE(expr, ...) \
do { \
if (!(expr)) { \
SOPHUS_DEDAULT_ENSURE_FAILURE_IMPL(SOPHUS_FUNCTION, __FILE__, __LINE__, \
##__VA_ARGS__); \
} \
} while (false)
为什么要把宏的定义包裹在 do { } while(false) 块中呢?
分析
主要是为了封闭代码,让宏定义被封闭在 do {} while(false) 中, 这样宏用在其他的程序结构中(比如 if ... else ... )就不容易出错。
在 C/C++ 中, 定义一个宏有很多种方法:
#define SET_MACRO_1() var1 = 0; var2 = 0;
#define SET_MACRO_2() { var1 = 0; var2 = 0; }
#define SET_MACRO_3() do { var1 = 0; var2 = 0; } while(false)
其中1、2两种用在 if/else 结构中就会出错,以第1种宏定义为例,放入如下的代码中:
if(ret)
SET_MACRO_1();
else
{
...
}
宏展开后变为:
if(ret)
var1 = 0; var2 = 0; ;
else
{
...
}
可以发现多了一个分号, 导致后面的 else 无法找到匹配的 if; 第2中宏定义也有类似的问题。
使用第3种 do { }while(false) 则没有这种问题,如下:
if(ret)
do { var1 = 0; var2 = 0; } while(false);
else
{
...
}