我试图弄清楚我的代码认为它正在使用哪个版本的 Boost。我想做这样的事情:
#error BOOST_VERSION
但预处理器不会扩展 BOOST_VERSION。
我知道我可以在程序运行时将其打印出来,并且我知道我可以查看预处理器的输出以找到答案。我觉得在编译期间有一种方法可能会很有用。
我知道这是在原始查询之后很长时间,但这可能仍然有用。
这可以在 GCC 中使用 stringify 运算符“#”来完成,但它需要两个阶段。
#define XSTR(x) STR(x) #define STR(x) #x
然后可以通过以下方式显示宏的值:
#pragma message "The value of ABC: " XSTR(ABC)
请参阅:gcc 在线文档中的 3.4 字符串化。
这个怎么运作:
预处理器理解带引号的字符串并以不同于普通文本的方式处理它们。字符串连接就是这种特殊处理的一个例子。消息杂注需要一个带引号的字符串的参数。当参数有多个组件时,它们必须都是字符串,以便可以应用字符串连接。预处理器永远不能假设一个未引用的字符串应该被视为被引用。如果是这样:
#define ABC 123 int n = ABC;
不会编译。
现在考虑:
#define ABC abc #pragma message "The value of ABC is: " ABC
这相当于
#pragma message "The value of ABC is: " abc
这会导致预处理器警告,因为 abc(未加引号)不能与前面的字符串连接。
现在考虑预处理器字符串化(它曾经被称为字符串化,文档中的链接已更改以反映修订后的术语。(顺便说一句,这两个术语同样令人讨厌。正确的术语当然是字符串化。准备好更新您的链接。))运算符。这仅作用于宏的参数,并用双引号括起来的参数替换未扩展的参数。因此:
#define STR(x) #x char *s1 = "abc"; char *s2 = STR(abc);
将为 s1 和 s2 分配相同的值。如果你运行 gcc -E 你可以在输出中看到这个。也许 STR 更适合命名为 ENQUOTE。
这解决了在未引用的项目周围加上引号的问题,现在的问题是,如果参数是宏,宏将不会被扩展。这就是需要第二个宏的原因。XSTR 扩展其参数,然后调用 STR 将扩展值放入引号中。