GCC转储预处理器定义

cs7cruho  于 2022-12-27  发布在  其他
关注(0)|答案(6)|浏览(167)

gcc/g++有没有办法从命令行转储它的默认预处理器定义呢?我指的是像__GNUC____STDC__这样的东西。

wbgh16ku

wbgh16ku1#

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

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的同义词。

hc2pp10m

hc2pp10m2#

我通常是这样做的:

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

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

$ 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
3ks5zfa0

3ks5zfa03#

  • 迟回答--我发现其他答案很有用--想多加一点。*
    如何转储来自特定头文件的预处理器宏?
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
$
z8dt9xmd

z8dt9xmd4#

简单的方法(gcc -dM -E - < /dev/null)对gcc很好用,但对g就不行了。最近我需要一个C11/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=c11)(发出错误消息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=gnu98)在默认情况下不启用C11特性,所以不会有输出。

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

最终产生

#define __cpp_alias_templates 200704

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

t3irkdon

t3irkdon5#

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

echo | gcc -dM -E -

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

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

它的工作原理是告诉gcc预处理stdin(由echo产生)和print all preprocessor defines(搜索-dletters).如果你想知道当你包含一个头文件时添加了什么定义,你可以使用-dD选项,它类似于-dM,但不包含预定义的宏:

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

但是,请注意,空输入仍然会使用-dD选项生成大量定义。

zphenhs4

zphenhs46#

当在一个大项目中工作时,它有复杂的构建系统,并且很难直接获得(或修改)gcc/g++命令,有另一种方法来查看宏扩展的结果。简单地重新定义宏,你会得到类似于下面的输出:

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

相关问题