GCC转储预处理器定义


Answers:


304

是的,使用-E -dM选项代替-c。示例(将它们输出到stdout):

 gcc -dM -E - < /dev/null

对于C ++

 g++ -dM -E -x c++ - < /dev/null

gcc手册

代替正常输出,为在预处理器执行期间定义的所有宏(包括预定义宏)生成一个“ #define”指令列表。这使您可以找到在您的预处理器版本中预定义的内容。假设您没有文件foo.h,该命令

touch foo.h; cpp -dM foo.h

将显示所有预定义的宏。

如果使用不带-E选项的-dM,则-dM被解释为-fdump-rtl-mach的同义词。


4
gcc存在于/ dev / null无效的系统上。
Pavel P

4
@Pavel然后,您可以使用带有gcc或预处理器-cpp的空文件。
philant 2014年

16
我添加了一种更可移植的方法作为替代答案:echo | gcc -dM -E -在Windows上也可以使用。
Pavel P

4
是否可以确定这些定义来自何处(即,在哪个文件中)?
edam 2014年

2
或者,可以在Windows cpp -dM -E - < NUL上使用。
勒内Nyffenegger

78

我通常这样做:

$ gcc -dM -E - < /dev/null

请注意,某些预处理器定义取决于命令行选项-您可以通过在上述命令行中添加相关选项来测试它们。例如,要查看默认情况下启用了哪些SSE3 / SSE4选项:

$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1

然后在-msse4指定时进行比较:

$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1

同样,您可以看到在两组不同的命令行选项之间哪些选项有所不同,例如,比较预处理器对优化级别-O0(无)和-O3(完整)的定义:

$ gcc -dM -E -O0 - < /dev/null > /tmp/O0.txt
$ gcc -dM -E -O3 - < /dev/null > /tmp/O3.txt
$ sdiff -s /tmp/O0.txt /tmp/O3.txt 
#define __NO_INLINE__ 1        <
                               > #define __OPTIMIZE__ 1

45

较晚的答案-我发现其他答案很有用-并希望添加一些额外的内容。


如何转储来自特定头文件的预处理器宏?

echo "#include <sys/socket.h>" | gcc -E -dM -

或(感谢@mymedia的建议):

gcc -E -dM -include sys/socket.h - < /dev/null

特别是,我想查看系统上为SOMAXCONN定义的内容。我知道我可以打开标准的头文件,但是有时我必须四处寻找头文件的位置。相反,我可以只使用这种单线:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 

1
您可以使用-include编译器选项来避免管道
mymedia

31

简单的方法(gcc -dM -E - < /dev/null)在gcc上工作正常,但在g ++上失败。最近,我需要对C ++ 11 / C ++ 14功能进行测试。有关其相应宏名称的建议,请参见https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations。但:

g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates

总是失败,因为它会静默地调用C驱动程序(就像由调用一样gcc)。您可以通过将其输出与gcc的输出进行比较,或添加特定于g ++的命令行选项(如(-std = c ++ 11))来显示此错误消息,以查看此信息cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C

由于(非C ++)gcc 永远不支持“模板别名”(请参见http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf),因此必须将-x c++选项添加到强制调用C ++编译器(使用-x c++选项而不是空的虚拟文件的信用转到yuyichao,请参见下文):

g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates

由于g ++(版本4.9.1,默认为-std = gnu ++ 98)默认情况下不会启用C ++ 11功能,因此将没有输出。为此,请使用

g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates

最终产生

#define __cpp_alias_templates 200704

请注意,使用调用时,g ++ 4.9.1确实支持“模板别名” -std=c++11


7
您不必使用虚拟文件。GCC支持该-x论据,因此g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cpp应该可行。
yuyichao 2015年

@yuyichao谢谢,这使它更易于使用。我不知道-x选项。提出您的评论,并将其整合到原始答案中。
hermannk

23

一种可移植的方法,在Linux或Windows(没有/ dev / null)上同样有效:

echo | gcc -dM -E -

对于c ++,您可以使用(替换c++11为您使用的任何版本):

echo | gcc -x c++ -std=c++11 -dM -E -

它通过告诉gcc预处理stdin(由echo生成)并打印所有预处理器定义(搜索-dletters)来工作。如果您想知道在包含头文件时添加的定义,可以使用-dD与-dM类似但不包含预定义宏的选项:

echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -

但是请注意,空输入仍然会产生大量带有-dDoption 的定义。


6
@rubenvb无关紧要。关键是要使cmd线至少在Windows和Unix上同样有效。如果使用NUL,则回到第一个平方:它在没有它的系统上不起作用。
Pavel P

2
添加C ++的完整答案,可以在Windows和Linux上运行(尽管sort行为稍有不同):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous

这会在git-bash中产生空输出。
Lennart Rolland '18

@LennartRolland是否有gcc?在我的git-bash中,我无法运行gcc
Pavel P

@pavel我使用Windows的Qt5二进制分发版附带的mingw32 gcc。
伦纳特·罗兰德'18

3

在具有复杂构建系统且难以直接获取(或修改)gcc / g ++命令的大型项目中工作时,还有另一种查看宏扩展结果的方法。只需重新定义宏,您将获得与以下类似的输出:

file.h: note: this is the location of the previous definition
#define MACRO current_value

我正在寻找使用什么警告标志。你知道吗 ?
Welgriv '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.