在升级编译器版本时,我遇到了一个需要注意的问题:
不必要地使用符号拼接运算符(##
)是不可移植的,并且可能会产生不必要的空格、警告或错误。
当符号拼接运算符的结果不是有效的预处理器标记时,该运算符是不必要且可能有害的。
例如,有人可能试图使用符号拼接运算符在编译时构建字符串字面量:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a##+##b)
#define NS(a, b) STRINGIFY(a##::##b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
在一些编译器上,这将输出预期的结果:
1+2 std::vector
在其他编译器中,这将包括不必要的空格:
1 + 2 std :: vector
相当现代的GCC版本(>=3.3左右)将无法编译此代码:
foo.cpp:16:1: pasting "1" and "+" does not give a valid preprocessing token
foo.cpp:16:1: pasting "+" and "2" does not give a valid preprocessing token
foo.cpp:16:1: pasting "std" and "::" does not give a valid preprocessing token
foo.cpp:16:1: pasting "::" and "vector" does not give a valid preprocessing token
解决方法是在将预处理器标记连接到C/C++操作符时省略标记粘贴运算符:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a+b)
#define NS(a, b) STRINGIFY(a::b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
关于标记粘贴运算符,GCC CPP文档的章节提供了更多有用的信息。
__LINE__
是一个特殊的宏名称,它会被预处理器替换为源文件中当前行的行号。 - Michael Burr