头文件中的变量定义

时间:2010-02-07 12:27:37

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

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

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

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

可能的解决方法:在头文件中使用标头保护并在其中定义变量。

它真的是一个解决方案:不会。因为标题保护用于预处理阶段。那就是告诉编译器这部分已经包含在内并且不再包含它。但是我们的多重定义错误来自链接器部分 - 在编译之后很久。

这一切让我对预处理和预处理方式感到困惑。连接工作。如果已经定义了头部保护符号,我认为预处理将不包括代码。在这种情况下,不应该解决变量问题的多重定义吗?

这些预处理指令会在标题保护下重新定义符号以保存编译过程,但链接器仍会获得符号的多个定义?

4 个答案:

答案 0 :(得分:26)

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

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不是标头保护,而是允许根据是否定义来声明/定义变量。该技术允许声明/定义的一个副本。

答案 1 :(得分:24)

Header guard可以保护您免受单个源文件中的多个包含,而不是来自多个源文件。我想你的问题源于不理解这个概念。

预编译器保护程序在编译期间不会从此问题中保存。实际上在编译期间,只有一个源文件被编译成一个obj,符号定义没有被解析。但是,如果在链接器尝试解析符号定义时进行链接,则会看到多个定义将其标记为错误而感到困惑。

答案 2 :(得分:10)

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

传统的解决方案是:

#ifdef DEFINE_SOMETHING
int something = 0;
#endif

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

答案 3 :(得分:8)

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