如何知道(在 GCC 中)何时声明了给定的宏/预处理器符号?

Posted

技术标签:

【中文标题】如何知道(在 GCC 中)何时声明了给定的宏/预处理器符号?【英文标题】:How to know (in GCC) when given macro/preprocessor symbol gets declared? 【发布时间】:2008-11-14 18:28:19 【问题描述】:

假设我在各种头文件中有#define foo。它可能会扩展到一些不同的事物。我想知道(在编译 .cc 文件时)遇到#define 时,它​​会扩展什么,它是哪个文件以及它是从哪里包含的。

有可能吗?如果没有,是否有任何可能有帮助的部分解决方案?

如有澄清请求,请随时添加 cmets。

编辑:当前的答案似乎集中在有一个#define 并且我只想跳到定义或知道定义是什么的情况上。这是简单的情况,是的,您的解决方案有效。但是当我在不同的文件中有相同的#define,并且想知道哪个是第一个启动时,这些技术都没有用。好的,我实际上使用#warning 仔细找到了正确的位置。但这需要做很多工作。

【问题讨论】:

当它在编译时运行到您的宏中时,您究竟希望它做什么? @Greg:打印信息:刚刚定义了这样的。将扩展到(...)。这是在文件 (...) 的行 (...) 中。包含自(“#includes 回溯到我的 .cc 文件)。 我对任何有影响的软件都有一种非常糟糕的感觉。 【参考方案1】:

使用 -E :

# shows preprocessed source with cpp internals removed
g++ -E -P file.cc
# shows preprocessed source kept with macros and include directives 
g++ -E -dD -dI -P file.cc  

上面的内部结构是 gcc 的行标记,当您阅读输出时会有点混乱。 -P 剥离它们

 -E 预处理阶段后停止;不要正确运行编译器。
     输出以预处理源代码的形式发送到
     标准输出。

     不需要预处理的输入文件将被忽略。

注意:cmets 正确地抱怨这只是部分解决方案。它不会告诉您何时替换宏。它会向您显示经过预处理的源代码,这无论如何都会有所帮助。

【讨论】:

这适用于整个文件,而不是单个#defines,它不提供@phjr 正在寻找的其余信息。 确实,这只是部分解决方案:) 如果不使用'-P'(保留内部),可以很容易地看到定义了文件宏。【参考方案2】:

我想知道(在编译 .cc 文件时)遇到#define 时,

I know a solution to that。使用已定义为非法 C++ 代码的符号编译文件(链接到的文章使用“@”)。所以,对于 GCC,你会写

gcc my_file.c -Dfoo=@

当它扩展时肯定会导致语法错误,编译器应该告诉你语法错误在哪个文件中,这将非常有帮助。

如果你使用 Raymond Chen 建议的技巧,编译器可能告诉你“冲突”定义的来源,可能给你一个它是如何得到的列表包括。但不能保证。因为我不使用宏(我更喜欢 const 和 enum),所以我不能说 GCC 是否是这方面更智能的编译器之一。我不相信 C 或 C++ 标准对此有任何说明,除非一旦预处理器运行,您就会丢失各种有用的信息。

【讨论】:

好主意,但如果定义由 #ifndef foo 保护,这将不起作用。【参考方案3】:

它不会帮助您找到它的定义位置,但您可以使用 -E -dM 标志查看特定文件的定义

g++ -E -dM file.cpp | grep MACRO

【讨论】:

然后从底部寻找你的宏。要知道该文件,您可以找到相应的 _HEADER_FILE_H 定义。【参考方案4】:

对于“它将扩展什么”,我使用 gcc 中的 -E 开关,它给出了预处理的输出。但是没有回溯哪个宏来自哪里(或者是否有宏)。

您可能使用的另一个选项是 -g3,这会添加有关宏的调试信息,即您稍后可以在调试器中查看每个宏的定义。

【讨论】:

【参考方案5】:

一个好的 IDE 可以通过某种形式的跳转到定义按需为您执行此操作。

【讨论】:

【参考方案6】:

使用#warning。它被描述为here。

【讨论】:

以上是关于如何知道(在 GCC 中)何时声明了给定的宏/预处理器符号?的主要内容,如果未能解决你的问题,请参考以下文章

GCC内置宏

C 中的预处理器指令:使用 __LINE__ 的宏

如何实现为 _Pragma 创建带引号的字符串的宏?

”更高级的宏“模板到底是怎么实例化的?

”更高级的宏“模板到底是怎么实例化的?

如何知道特定的预处理器指令是不是在第三方 DLL 中定义?