当前位置:  开发笔记 > 前端 > 正文

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

如何解决《如何在编译时显示#define的值?》经验,为你挑选了7个好方法。

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

#error BOOST_VERSION

但预处理器不会扩展BOOST_VERSION.

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



1> Jackie Yeh..:

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


很好的解决方案。但是,如果我希望显示编译时计算值的大小,例如复杂结构的大小,可以这样做吗?在此答案中建议的方法似乎生成了DEFINED_INT =(sizeof(MY_STRUCT)),而没有对sizeof运算符进行评估。

2> Chris Barry..:

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

这可以使用stringify运算符"#"在GCC中完成,但它需要两个阶段.

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

然后可以显示宏的值:

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

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


@VincentFourmond没有XSTR阶段,宏不会扩展.所以如果你做#define ABC 42 \n STR(ABC),你会得到"ABC".请参阅https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
我很好奇它为什么需要两个阶段

3> Bojan Resnik..:

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

#include 
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

编辑:感谢LB的链接

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

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)


这就是所谓的诊断实用程序,http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
如果你包括[BOOST_PP_STRINGIZE`的定义](http://www.boost.org/doc/libs/1_63_0/boost/preprocessor/stringize.hpp),这很好,很短,可以复制/粘贴.

4> KeyserSoze..:

据我所知'#error'只打印字符串,实际上你甚至不需要使用引号.

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



5> 小智..:

没有提升:

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

    从警告中,您可以看到先前定义的位置.

    以前定义的vi文件.

ambarish@axiom:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}



6> UweBaemayr..:

在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



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

即使preprocess to file已启用,即使存在无效令牌也可以使用:

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

推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有