如何在编译时显示#define的值?

时间:2009-10-13 18:26:18

标签: macros c-preprocessor boost-preprocessor

我试图找出我的代码认为它正在使用的Boost版本。我想做这样的事情:

#error BOOST_VERSION

但预处理器不会扩展BOOST_VERSION。

我知道我可以在程序运行时打印出来,我知道我可以查看预处理器的输出来找到答案。我觉得在编译期间有一种方法可以使用它。

14 个答案:

答案 0 :(得分:107)

BOOST_PP_STRINGIZE似乎是C ++的绝佳解决方案,但不适用于常规C。

以下是我对GNU CPP的解决方案:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

以上定义导致:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

对于“定义为interger”“定义为字符串”“已定义但没有值”变量,它们工作得很好。仅对于“未定义”变量,它们显示与原始变量名称完全相同。你必须习惯它 - 或者有人可以提供更好的解决方案。

答案 1 :(得分:87)

我知道这是在原始查询之后很长一段时间,但这可能仍然有用。

这可以使用stringify运算符“#”在GCC中完成,但需要两个阶段。

#define XSTR(x) STR(x)
#define STR(x) #x

然后可以使用以下内容显示宏的值:

#pragma message "The value of ABC: " XSTR(ABC)

请参阅:3.4 gcc在线文档中的字符串化。

答案 2 :(得分:54)

如果您使用的是Visual C ++,则可以使用#pragma message

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

修改:感谢LB提供链接

显然,GCC等价物是(未经测试):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

答案 3 :(得分:11)

据我所知,'#error'只打印字符串,实际上是you don't even need to use quotes

您是否尝试使用“BOOST_VERSION”编写各种故意错误的代码?也许就像“blah [BOOST_VERSION] = foo;”会告诉你类似“字符串文字1.2.1不能用作数组地址”。它不会是一个错误的错误消息,但至少它会显示相关的值。你可以玩,直到找到一个告诉你值的编译错误。

答案 4 :(得分:9)

没有提升:

  1. 再次定义相同的宏,编译器HIMSELF将发出警告。

  2. 从警告中您可以看到上一个定义的位置。

  3. 以前定义的vi文件。

  4. foo

答案 5 :(得分:4)

#define a <::BOOST_VERSION>
#include a
MSVC2015 :致命错误C1083:无法打开包含文件:&#39; :: 106200&#39;:没有此类文件或目录

即使启用了preprocess to file,即使存在无效令牌,也可以正常工作:

#define a <::'*/`#>
#include a
MSVC2015 :致命错误C1083:无法打开包含文件:&#39; ::&#39; * /`#&#39;:没有此类文件或目录
GCC4.x :警告:缺少终止&#39;字符[-Winvalid-pp-token]
    #define a&lt; ::&#39; * /`#&gt;

答案 6 :(得分:2)

您还可以预处理源文件,并查看预处理器值的计算结果。

答案 7 :(得分:2)

在Microsoft C / C ++中,可以使用内置的_CRT_STRINGIZE()打印常量。我的许多stdafx.h文件都包含以下内容的组合:

#pragma message("_MSC_VER      is " _CRT_STRINGIZE(_MSC_VER))
#pragma message("_MFC_VER      is " _CRT_STRINGIZE(_MFC_VER))
#pragma message("_ATL_VER      is " _CRT_STRINGIZE(_ATL_VER))
#pragma message("WINVER        is " _CRT_STRINGIZE(WINVER))
#pragma message("_WIN32_WINNT  is " _CRT_STRINGIZE(_WIN32_WINNT))
#pragma message("_WIN32_IE     is " _CRT_STRINGIZE(_WIN32_IE))
#pragma message("NTDDI_VERSION is " _CRT_STRINGIZE(NTDDI_VERSION)) 

并输出如下内容:

_MSC_VER      is 1915
_MFC_VER      is 0x0E00
_ATL_VER      is 0x0E00
WINVER        is 0x0600
_WIN32_WINNT  is 0x0600
_WIN32_IE     is 0x0700
NTDDI_VERSION is 0x06000000

答案 8 :(得分:1)

您在寻找

吗?
#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

如果BOOST_VERSION是一个字符串,就像我假设的那样,不是很好,但是也可能有为主要,次要和修订号定义的单个整数。

答案 9 :(得分:1)

查看预处理器的输出与您要求的答案最接近。

我知道你已经排除了(以及其他方式),但我不确定为什么。你有一个特定的问题要解决,但你没有解释为什么任何“正常”的方法都不适合你。

答案 10 :(得分:0)

您可以编写一个打印出BOOST_VERSION的程序,并将其作为构建系统的一部分进行编译和运行。否则,我认为你运气不好。

答案 11 :(得分:0)

BOOST_VERSION在boost头文件version.hpp中定义。

答案 12 :(得分:0)

看一下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

  

描述了增强版本号   XXYYZZ格式使:    (BOOST_VERSION % 100) 是次要的   版本, ((BOOST_VERSION / 100) %    1000) 是次要版本,并且    (BOOST_VERSION / 100000) 是主要的   版本

答案 13 :(得分:0)

而不是#error,而是在使用宏之前尝试重新定义宏。编译将失败,编译器将提供它认为适用于宏的当前值。

#define BOOST_VERSION等