C - #include 预处理器宏命名空间



这个问题是为了理解头文件包含的标准行为(不是在我的编译器上实现的行为)。

我有两个同名的头文件(但内容不同):

1) /user/include/myheader.h  # In standard system folder
2) /private/myheader.h       # In my private folder

假设两个标头都包含相同的多重包含预处理宏

#ifndef MYHEADER
#define MYHEADER
...
#endif

我有 C 文件/private/test.c,其中包括上述两个标头:

#include <myheader.h>  // Includes from standard system folder
#include "myheader.h"  // Includes from the folder where test.c is present

预处理时,两个文件的内容是否进入 C 文件,因为每个 MYHEADER 定义都有单独的命名空间?或者第二个包含将被阻止,因为 MYHEADER 已经在同一命名空间中定义?

所有宏只有一个命名空间,所有宏都位于同一命名空间中。 将内容放在不同的头文件中对此没有影响 - 它们仍然位于同一个命名空间中。 因此,在您的示例中,第一个标头将定义 MYHEADER ,这将导致(有效地)忽略第二个标头。

N1570:

6.10.3 宏替换

...
7 紧跟在define后面的标识符称为宏名称有一个宏名称的名称空间。在预处理令牌的替换列表不被视为任一形式的宏的替换列表的一部分。

强调我的。

如前所述,将仅处理第一个myheader.h文件的内容。

在 C 标准1 中,预处理器定义没有"命名空间"这样的东西。无论MYHEADER如何定义2,第二个文件的内容都将被忽略。


1 C99标准第6.2.3节定义了四个名称空间 - (1)用于标签,(2)用于结构/联合/枚举标签,(3)用于每个结构或联合的成员,以及(4)用于其他所有内容。预处理器定义不属于这些名称空间中的任何一个,因为"此处不进一步考虑宏名称和宏参数,因为在程序转换的语义阶段之前,源文件中出现的任何宏名称都将替换为构成其宏定义的预处理标记序列。

2 就定义MYHEADER而言,您有几种选择:您可以在 C 文件、头文件中定义它,或者使用 C 编译器的相应选项从命令行传递它。

只使用一个定义,因为 #define 指令具有全局范围,因此第二个包含将不执行任何操作。

您应该使用MY_PROJECT_MY_HEADER或类似的东西来防止此类问题。

最新更新