GCC 转储预处理器定义

问题描述 投票:0回答:6

gcc/g++ 有没有办法从命令行转储其默认预处理器定义? 我的意思是

__GNUC__
__STDC__
等等。

gcc g++ c-preprocessor
6个回答
387
投票

是的,使用

-E
-dM
选项而不是 -c。 示例(将它们输出到标准输出):

 echo | gcc -dM -E -
 echo | clang -dM -E -

对于C++

 echo | g++ -dM -E -x c++ -
 echo | clang++ -dM -E -x c++ -

摘自GCC手册

代替正常输出,生成 所有指令的“#define”列表 期间定义的宏 预处理器的执行, 包括预定义的宏。这 为您提供一种了解是什么的方法 在您的版本中预定义的 预处理器。假设你没有 文件 foo.h,命令

touch foo.h; cpp -dM foo.h

将显示所有预定义的宏。

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


87
投票

我通常这样做:

$ 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

50
投票

迟到的答案 - 我发现其他答案很有用 - 并且想添加一些额外的内容。


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

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
$ 

34
投票

简单的方法 (

gcc -dM -E - < /dev/null
) 对于 gcc 工作得很好,但对于 g++ 却失败了。最近我需要测试 C++11/C++14 功能。相应宏名称的建议发布于 https://isocpp.org/std/stand-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
调用时确实支持“模板别名”。


26
投票

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

echo | gcc -dM -E -

对于 c++,您可以使用(将

c++11
替换为您使用的任何版本):

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

它的工作原理是告诉 gcc 预处理标准输入(由 echo 生成)并打印所有预处理器定义(搜索

-dletters
)。如果您想知道在包含头文件时添加了哪些定义,您可以使用-dD
选项,该选项类似于-dM,但不包含预定义的宏:

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

但是请注意,空输入仍然会使用

-dD

 选项生成大量定义。


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

file.h: note: this is the location of the previous definition #define MACRO current_value
    
© www.soinside.com 2019 - 2024. All rights reserved.