GCC转储预处理器定义

Any*_*orn 232 gcc g++ c-preprocessor

有没有办法让gcc/g ++从命令行转储它的预处理器定义?我的意思是__GNUC__,__STDC__等等.

phi*_*ant 285

是的,使用-E -dM选项而不是-c.示例(将它们输出到stdout):

 gcc -dM -E - < /dev/null
Run Code Online (Sandbox Code Playgroud)

对于C++

 g++ -dM -E -x c++ - < /dev/null
Run Code Online (Sandbox Code Playgroud)

gcc手册:

而不是正常输出,为执行预处理器期间定义的所有宏生成一个"#define"指令列表,包括预定义的宏.这为您提供了一种查找预处理器版本中预定义内容的方法.假设你没有文件foo.h,那么命令

touch foo.h; cpp -dM foo.h
Run Code Online (Sandbox Code Playgroud)

将显示所有预定义的宏.

如果在没有-E选项的情况下使用-dM,则-dM将被解释为-fdump-rtl-mach的同义词.

  • 我添加了一种更便携的方法作为替代答案:`echo | gcc -dM -E -`也适用于Windows. (16认同)
  • @Pavel然后你可以使用一个空文件,使用gcc或预处理器--cpp. (4认同)
  • 是否有可能确定这些定义的来源(即哪个文件)? (4认同)
  • gcc存在于/ dev/null没有任何意义的系统上. (3认同)
  • 或者,在 Windows 上,可以使用 `cpp -dM -E - &lt; NUL`。 (3认同)
  • @edam要确定宏的来源,请查看此处:http://stackoverflow.com/questions/11257455/how-to-find-the-source-of-some-macros (2认同)
  • 如果您要打印 c++ 定义宏,请不要忘记 '-x c++' 命令行标志。完整的命令是: 'g++ -x c++ -dM -E - &lt; /dev/null' 用于 C++ 特定的宏。 (2认同)

Pau*_*l R 77

我通常这样做:

$ gcc -dM -E - < /dev/null
Run Code Online (Sandbox Code Playgroud)

请注意,某些预处理器定义依赖于命令行选项 - 您可以通过将相关选项添加到上述命令行来测试这些选项.例如,要查看默认情况下启用了哪些SSE3/SSE4选项:

$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1
Run Code Online (Sandbox Code Playgroud)

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

$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1
Run Code Online (Sandbox Code Playgroud)

类似地,您可以看到两个不同的命令行选项集之间有哪些选项不同,例如,比较预处理器定义的优化级别-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
Run Code Online (Sandbox Code Playgroud)


Dig*_*uma 42

迟到的答案 - 我发现其他答案很有用 - 并希望增加一些额外的答案.


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

echo "#include <sys/socket.h>" | gcc -E -dM -
Run Code Online (Sandbox Code Playgroud)

特别是,我想看看SOMAXCONN在我的系统中定义了什么.我知道我可以打开标准的头文件,但有时我必须搜索一下才能找到头文件的位置.相反,我可以使用这个单行:

$ echo "#include <sys/socket.h>" | gcc -E -dM - | grep SOMAXCONN
#define SOMAXCONN 128
$ 
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用 [-include](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Preprocessor-Options.html) 编译器选项来避免管道 (5认同)

her*_*nnk 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
Run Code Online (Sandbox Code Playgroud)

总是失败,因为它默默地调用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++选项而不是空虚拟文件的Credits 转到yuyichao,见下文):

g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates
Run Code Online (Sandbox Code Playgroud)

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

g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates
Run Code Online (Sandbox Code Playgroud)

最终收益

#define __cpp_alias_templates 200704
Run Code Online (Sandbox Code Playgroud)

注意到g ++ 4.9.1在调用时支持"模板别名" -std=c++11.

  • 您不必使用虚拟文件.GCC支持`-x`参数,所以`g ++ -x c ++ -dM -E -std = c ++ 11 - </ dev/null | grep cpp`应该工作. (7认同)

Pav*_*l P 23

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

echo | gcc -dM -E -
Run Code Online (Sandbox Code Playgroud)

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

echo | gcc -x c++ -std=c++11 -dM -E -
Run Code Online (Sandbox Code Playgroud)

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

echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -
Run Code Online (Sandbox Code Playgroud)

但请注意,空输入仍会产生大量带-dD选项的定义.

  • @rubenvb它无关紧要.关键是要使cmd行在windows和unix上工作得相同.如果您使用`NUL`,那么您将回到原点:它将无法在没有它的系统上运行. (6认同)
  • 为C++添加完整的答案,适用于Windows和Linux(尽管`sort`行为略有不同):`echo | gcc -x c ++ -std = c ++ 17 -dM -E - | sort` (2认同)