【问题标题】:Should variable definition be in header files?变量定义应该在头文件中吗?
【发布时间】:2011-01-14 01:51:49
【问题描述】:

我对 C 和编译过程的基本知识最近已经生疏了。我试图找出以下问题的答案,但我无法连接编译、链接和预处理阶段的基础知识。在谷歌上快速搜索也没有多大帮助。所以,我决定来到知识的终极来源:)

我知道:不应在 .h 文件中定义变量。可以在那里声明它们。

原因:因为一个头文件可能会从多个位置包含进来,因此多次重新定义变量(链接器给出错误)。

可能的解决方法:在头文件中使用 header-guards 并在其中定义变量。

这真的是一个解决方案吗: 不。因为标头守卫用于预处理阶段。就是告诉编译器这部分已经包含了,不要再包含了。但是我们的多重定义错误出现在链接器部分——在编译之后。

这整件事让我对预处理和链接的工作方式感到困惑。我认为如果已定义标头保护符号,预处理将不包含代码。那样的话,变量问题的多重定义不也应该得到解决吗?

如果这些预处理指令使编译过程免于在标头保护下重新定义符号,但链接器仍然获得符号的多个定义,会发生什么情况?

【问题讨论】:

    标签: c linker c-preprocessor header-files include-guards


    【解决方案1】:

    标头保护可保护您免受单个源文件中的多个包含,而不是多个源文件。我猜你的问题源于不理解这个概念。

    并不是说预处理器保护在编译期间从这个问题中节省下来。实际上在编译期间,只有一个源文件被编译成一个 obj,符号定义没有被解析。但是,如果在链接器尝试解析符号定义时进行链接,它会因为看到多个定义导致它标记错误而感到困惑。

    【讨论】:

      【解决方案2】:

      标头保护阻止标头文件被多次包含在同一翻译单元中(即在同一个 .c 源文件中)。如果您将文件包含在两个或更多翻译单元中,它们将无效。

      【讨论】:

        【解决方案3】:

        我过去使用过的一件事(当全局变量流行时):

        var.h 文件:

        ...
        #ifdef DEFINE_GLOBALS
        #define EXTERN
        #else
        #define EXTERN extern
        #endif
        EXTERN int global1;
        EXTERN int global2;
        ...
        

        然后在一个.c文件中(通常是包含main()的那个):

        #define DEFINE_GLOBALS
        #include "var.h"
        

        其余的源文件通常只包含“var.h”。

        请注意,DEFINE_GLOBALS 不是标头保护,而是允许根据是否定义变量来声明/定义变量。这种技术允许声明/定义的一份副本。

        【讨论】:

          【解决方案4】:

          您有两个 .c 文件。它们被单独编译。每一个都包含你的头文件。一次。每个人都有一个定义。它们在链接时发生冲突。

          常规的解决方案是:

          #ifdef DEFINE_SOMETHING
          int something = 0;
          #endif
          

          然后你在只有一个 .c 文件中#define DEFINE_SOMETHING。

          【讨论】:

          • 更好的解决方案是在标头中声明,并且仅在一个 .c 文件中进行定义。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-03
          • 1970-01-01
          • 1970-01-01
          • 2023-03-12
          • 2011-09-10
          • 2014-08-04
          相关资源
          最近更新 更多