如何在编译时显示 #define 的值?
我试图找出我的代码认为它使用的 Boost 版本。我想做这样的事情:
#error BOOST_VERSION
但预处理器不会扩展 BOOST_VERSION。
我知道我可以在程序运行时将其打印出来,并且我知道我可以查看预处理器的输出来找到答案。我觉得在编译过程中找到一种方法可能会很有用。
I am trying to figure out what version of Boost my code thinks it's using. I want to do something like this:
#error BOOST_VERSION
but the preprocessor does not expand BOOST_VERSION.
I know I could print it out at run-time from the program, and I know I could look at the output of the preprocessor to find the answer. I feel like having a way of doing this during compilation could be useful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我知道这距离原始查询已经过去很长时间了,但这可能仍然有用。
这可以在 GCC 中使用字符串化运算符“#”来完成,但需要首先定义两个附加阶段。
然后可以使用以下命令显示宏的值:
请参阅:gcc 在线文档中的 3.4 字符串化。
工作原理:
预处理器理解带引号的字符串,并以不同于普通文本的方式处理它们。字符串连接是这种特殊处理的一个例子。消息杂注需要一个带引号的字符串参数。当参数有多个组件时,它们必须都是字符串,以便可以应用字符串连接。预处理器永远不能假设应将未加引号的字符串视为已加引号的字符串。如果这样做的话:
将无法编译。
现在考虑:
这相当于
这会导致预处理器警告,因为 abc (不带引号)无法与前面的字符串连接。
现在考虑预处理器 stringize (曾经被称为 stringification,文档中的链接已更改以反映修订后的术语。(顺便说一句,这两个术语同样令人讨厌。当然,正确的术语是 stringifaction。准备好更新您的链接。))运营商。这只作用于宏的参数,并将未展开的参数替换为用双引号括起来的参数。因此:
将为 s1 和 s2 分配相同的值。如果运行 gcc -E 您可以在输出中看到这一点。也许 STR 更适合命名为 ENQUOTE 之类的名称。
这解决了在未加引号的项目周围加上引号的问题,现在的问题是,如果参数是宏,则宏将不会被扩展。这就是需要第二个宏的原因。 XSTR 扩展其参数,然后调用 STR 将扩展的值放入引号中。
I know that this is a long time after the original query, but this may still be useful.
This can be done in GCC using the stringify operator "#", but it requires two additional stages to be defined first.
The value of a macro can then be displayed with:
See: 3.4 Stringification in the gcc online documentation.
How it works:
The preprocessor understands quoted strings and handles them differently from normal text. String concatenation is an example of this special treatment. The message pragma requires an argument that is a quoted string. When there is more than one component to the argument then they must all be strings so that string concatenation can be applied. The preprocessor can never assume that an unquoted string should be treated as if it were quoted. If it did then:
would not compile.
Now consider:
which is equivalent to
This causes a preprocessor warning because abc (unquoted) cannot be concatenated with the preceding string.
Now consider the preprocessor stringize (Which was once called stringification, the links in the documentation have been changed to reflect the revised terminology. (Both terms, incidentally, are equally detestable. The correct term is, of course, stringifaction. Be ready to update your links.)) operator. This acts only on the arguments of a macro and replaces the unexpanded argument with the argument enclosed in double quotes. Thus:
will assign identical values to s1 and s2. If you run gcc -E you can see this in the output. Perhaps STR would be better named something like ENQUOTE.
This solves the problem of putting quotes around an unquoted item, the problem now is that, if the argument is a macro, the macro will not be expanded. This is why the second macro is needed. XSTR expands its argument, then calls STR to put the expanded value into quotes.
BOOST_PP_STRINGIZE
对于 C++ 来说似乎是一个很好的解决方案,但对于常规 C 来说却不是。这是我对 GNU CPP 的解决方案:
以上定义的结果是:
对于“定义为整数”,“定义为字符串”和“定义但没有值”变量,它们工作得很好。仅对于“未定义”变量,它们显示与原始变量名称完全相同。你必须习惯它——或者也许有人可以提供更好的解决方案。
BOOST_PP_STRINGIZE
seems a excellent solution for C++, but not for regular C.Here is my solution for GNU CPP:
Above definitions result in:
For "defined as interger", "defined as string", and "defined but no value" variables , they work just fine. Only for "not defined" variable, they displayed exactly the same as original variable name. You have to used to it -- or maybe someone can provide a better solution.
如果您使用的是 Visual C++,则可以使用
#pragma message
:编辑: 感谢 LB 提供的链接
显然,GCC 等效项是(未测试):
If you are using Visual C++, you can use
#pragma message
:Edit: Thanks to LB for link
Apparently, the GCC equivalent is (not tested):
据我所知 '#error' 只会打印字符串,事实上你甚至不需要使用引号。
您是否尝试过使用“BOOST_VERSION”编写各种故意不正确的代码?也许类似于“blah[BOOST_VERSION] = foo;”会告诉你类似“字符串文字 1.2.1 不能用作数组地址”之类的信息。这不会是一个漂亮的错误消息,但至少它会向您显示相关的值。您可以尝试一下,直到找到确实告诉您该值的编译错误。
As far as I know '#error' only will print strings, in fact you don't even need to use quotes.
Have you tried writing various purposefully incorrect code using "BOOST_VERSION"? Perhaps something like "blah[BOOST_VERSION] = foo;" will tell you something like "string literal 1.2.1 cannot be used as an array address". It won't be a pretty error message, but at least it'll show you the relevant value. You can play around until you find a compile error that does tell you the value.
没有 boost :
再次定义相同的宏,编译器 HIMSELF 将给出警告。
从警告中您可以看到先前定义的位置。
先前定义的 vi 文件。
Without boost :
define same macro again and compiler HIMSELF will give warning.
From warning you can see location of the previous definition.
vi file of previous definition .
在 Microsoft C/C++ 中,您可以使用内置的
_CRT_STRINGIZE()
来打印常量。我的许多stdafx.h
文件包含以下内容的某种组合:并输出如下内容:
In Microsoft C/C++, you can use the built-in
_CRT_STRINGIZE()
to print constants. Many of mystdafx.h
files contain some combination of these:and outputs something like this:
优点:
预处理到文件
,即使存在无效令牌,也可以工作:缺点:
更新:
对于 GCC 4.7.x 及更低版本,输出会引发错误:
要解决此问题,您可以更改前缀:
Pros:
preprocess to file
is enabled, even if invalid tokens are present:Cons:
Update:
For GCC 4.7.x and lower the output throws the error:
To fix that you can change the prefix:
您还可以预处理源文件并查看预处理器值的计算结果。
You could also preprocess the source file and see what the preprocessor value evaluates to.
查看预处理器的输出是最接近您要求的答案的。
我知道你已经排除了这一点(以及其他方式),但我不确定为什么。您有一个足够具体的问题需要解决,但您没有解释为什么任何“正常”方法都不适合您。
Looking at the output of the preprocessor is the closest thing to the answer you ask for.
I know you've excluded that (and other ways), but I'm not sure why. You have a specific enough problem to solve, but you have not explained why any of the "normal" methods don't work well for you.
您可以编写一个程序来打印
BOOST_VERSION
并将其作为构建系统的一部分进行编译和运行。不然我觉得你运气不好。You could write a program that prints out
BOOST_VERSION
and compile and run it as part of your build system. Otherwise, I think you're out of luck.您是否正在寻找
Not Great if BOOST_VERSION 是一个字符串,就像我假设的那样,但也可能为主要、次要和修订号定义了单独的整数。
Are you looking for
Not great if BOOST_VERSION is a string, like I've assumed, but there may also be individual integers defined for the major, minor and revision numbers.
BOOST_VERSION 在 boost 头文件 version.hpp 中定义。
BOOST_VERSION is defined in the boost header file version.hpp.
另请参阅 Boost 文档,了解如何使用宏:
参考
BOOST_VERSION
,来自 http://www.boost.org/doc/libs/1_37_0/libs/config/doc /html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.boost_helper_macros:Take a look at the Boost documentation as well, regarding how you are using the macro:
In reference to
BOOST_VERSION
, from http://www.boost.org/doc/libs/1_37_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.boost_helper_macros:在编译时打印扩展的宏值
这是@Jackie Yeh 的答案的扩展。
神奇的助手宏,经过我的一些小调整:
使用它们:
警告:如果宏未定义,它的名称将再次打印出来!因此,如果您的宏名为
MY_MACRO
,但您从未定义它,则执行以下操作:...将打印出如下内容:
因此,搜索
#pragma message:
在构建输出中查看打印的宏值。并且,在编译时查找MY_MACRO=`MY_MACRO`
类型输出,这是MY_MACRO
未定义的明确标志!这让我有一段时间感到困惑,我失去了很多时间没有意识到这一点。
我想证明这也适用于代码块。所以,这是我的完整示例:
macro_print_macro_values_at_compile_time.c
来自我的 eRCaGuy_hello_world 存储库:构建并运行命令,并输出,在 C 和 C++ 中:
在 C 中:
或者在 C++ 中:
相邻相关
sizeof( )
) C 和 C++ 编译时错误消息中的类型或变量Print expanded macro values at compile-time
This is an extension of @Jackie Yeh's answer here.
The magic helper macros, with my minor tweaks:
To use them:
A word of caution: if the macro is not defined, its name will just be printed out again! So, if your macro is called
MY_MACRO
, but you never define it, then doing this:...will print out something like this:
So, do a search for
#pragma message:
in your build output to see the printed macro values. And, look forMY_MACRO=`MY_MACRO`
type output when compiling as a clear sign thatMY_MACRO
is not defined!This threw me off for a while and I lost a lot of time not realizing this.
I want to show that this works with code blocks too. So, here's my full example:
macro_print_macro_values_at_compile_time.c
from my eRCaGuy_hello_world repo:Build and run commands, and output, in both C and C++:
In C:
Or, in C++:
Adjacently-related
sizeof()
) a type or variable in an error message at compile time in both C and C++尝试在使用宏之前重新定义宏,而不是#error。编译将失败,编译器将提供它认为适用于宏的当前值。
#define BOOST_VERSION 等等
Instead of #error, try redefining the macro, just before it is being used. Compilation will fail and compiler will provide the current value it thinks applies to the macro.
#define BOOST_VERSION blah