在不同的头文件中使用同名的宏

Posted

技术标签:

【中文标题】在不同的头文件中使用同名的宏【英文标题】:Using macros with the same name in different header files 【发布时间】:2021-02-02 03:54:08 【问题描述】:

我使用 #DEBUG 之类的宏来打印一些额外的调试信息,甚至可能做一些不同的事情来帮助我进行调试。例如:

在标题 a.h 中:

#define DEBUG 1

在 src 交流中:

#include "a.h"

int func_a () 
/*some code*/
#if DEBUG
//do this
#endif

如果我在另一个文件中使用同名的宏会怎样?

标题 b.h

#define DEBUG 1
#if DEBUG
    # define PRINT 1
#elif
    #define PRINT 0
#endif

src b.c

#include "a.h"
#include "b.h"

int func_b () 
/*some code*/
#if PRINT
//do this
#endif
/*some code*/
#if DEBUG
//do this
#endif

如果我在其中一个标题中更改#DEBUG 的值会发生什么?我在其他一些答案中看到,在 C 标准中不允许重新定义宏。但是当我使用 -Wall 标志使用 GCC 编译时,我看不到任何错误或警告。

【问题讨论】:

如果您在单个translation unit 中多次定义宏,您应该会收到错误或警告。您使用哪个版本的 GCC?你是如何构建你的程序的?您显示的代码是实际的minimal reproducible example,可用于复制缺少警告吗? 如果定义相同,gcc 似乎不会出错。 C11 6.10.3p2bop @Someprogrammerdude 允许使用相同的定义(如本例)重新定义宏。 值得一提的是,要检查是否定义了宏,您可能应该使用ifdefifndefif defined(MACRONAME) interjay 对这个问题有正确的答案 - 使用相同的定义重新定义应该没问题,但不允许使用不同的定义重新定义相同的宏,并且应该出错 【参考方案1】:

如果我在另一个文件中使用同名的宏会怎样?

这取决于。 C 不允许在翻译单元中的某个点处已定义为宏名称的标识符在该点处再次定义,除非重新定义指定了相同的替换列表。这是一种语言约束,因此符合要求的实现将发出关于他们感知到的违规的诊断信息。编译器可能会拒绝包含违规的代码,如果他们仍然接受这样的代码,那么就 C 而言,结果行为是未定义的。

在实践中,接受此类违规行为的实现有两个合理的选择(以及一系列不合理的选择):

忽略重新定义,或 处理重新定义,就好像它是由指定受影响的宏名称的#undefine 指令进行的一样。

我知道的实现接受这样的重新定义并实现后一个选项,至少在默认情况下。

如果您的标头仅为其内部使用而定义宏,那么您可以通过一些纪律来解决该问题:

    每个标头都将其所有 #include 指令放在开头,在任何可能冲突的宏的定义之前。 每个标头#undefines 末尾可能有冲突的宏,在所有条件编译场景中,宏可能首先被定义。

另一方面,如果宏打算被使用定义它的头文件的文件引用,那么在头文件中取消定义它会破坏目的。在某些情况下,可能包括您的情况,您可以通过仅在每个标题中有条件地定义宏来解决这个问题:

#if !defined(DEBUG)
#define DEBUG 1
#endif

这将避免重新定义,而是使用(仅)遇到的第一个定义,它甚至可能来自编译器命令行参数。但是,如果您这样做,那么以这种方式指定的所有默认定义都必须相同,否则更改标头的包含顺序将产生意想不到的效果代码,具体取决于使用的定义。

【讨论】:

以上是关于在不同的头文件中使用同名的宏的主要内容,如果未能解决你的问题,请参考以下文章

Q_UNUSED()宏头文件

Q_UNUSED()宏头文件

关于XCode工程中PrefixHead.pch文件的使用

iOS之pch文件的正确使用

iOS开发中.pch 文件的使用及其相关工程设置

c语言的宏定义 if defined