【问题标题】:#include preprocessor macro name space#include 预处理器宏名称空间
【发布时间】:2012-09-19 18:02:02
【问题描述】:

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

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

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

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

【问题讨论】:

  • 除非你在某个地方#undef MYHEADER,否则第二个包含基本上会包含一个空文件。

标签: c linux gcc


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    N1570:

    6.10.3 宏替换

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

    强调我的。

    正如所写,只会处理第一个myheader.h 文件的内容。

    【讨论】:

      【解决方案3】:

      C 标准1 中没有用于预处理器定义的“名称空间”。无论MYHEADER如何定义2,第二个文件的内容都会被忽略。


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

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

      【讨论】:

      • 但是,prase“命名空间”在 C11 标准中出现了 19 次。
      • @JohnBode 这不会以任何方式改变我的答案的正确性:C11 标准中也没有“命名空间”这个词。我确实编辑了我的答案以包含标准中的更多细节,主要是为了表明“名称空间”不适用于预处理器定义。
      • 按照我阅读 6.3.10/7 和 6.2.3/1 的方式,听起来预处理器定义占用了与普通标识符不同的命名空间。
      【解决方案4】:

      将只使用一个定义,因为#define 指令具有全局范围,因此第二个包含将什么都不做。

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

      【讨论】:

        猜你喜欢
        • 2021-10-27
        • 1970-01-01
        • 2013-01-25
        • 2010-09-25
        • 2019-07-08
        • 2015-04-15
        • 2015-07-31
        • 1970-01-01
        相关资源
        最近更新 更多