在同一个头文件中定义extern变量

6

我想知道是否可能在同一个头文件中同时声明和定义一个外部变量。我需要在多个文件中引用这个变量,虽然我意识到有更好的方法来实现这一点,但在这种情况下使用extern是唯一的选择。那么是否可以这样做:

// in main.h
extern int foo;
int foo;

etc...

那么任何包含main.h文件的文件都将可以访问foo变量?很多例子都提到在另一个cpp文件中定义extern变量,但我只是想知道我所建议的方法是否会在项目的其他部分引起问题。


4
请了解一定义规则并询问您是否可以违反它。 - Drew Dormann
1
这是可能的,但不是一个好主意。应该只有一个实际定义,由需要它的所有内容共享,并且其他所有内容都将链接到它--如果您在头文件中定义它,则会得到多个定义(每个包含头文件的翻译单元中都有一个),这违背了使用extern的目的。如果您只使用头文件一次,它将起作用。 - Dmitri
请参考其他的SO问题,如何在C语言中使用extern来共享源文件之间的变量? - Jonathan Leffler
在头文件中声明任何变量、结构体实例或联合实例都是一个(几乎总是)不好的主意,因为每个包含该头文件的文件都会有另一个这样的变量实例。强烈建议:在某个源文件中声明变量实例,并且只在头文件中使用“extern”语句。 - user3629249
3个回答

14

如果您将定义放在头文件中,当涉及多个源文件时,您将得到多个定义。

例如,假设main.cother.c都包含foo.h。 当编译这些文件时,您将得到main.oother.o,两者都有int foo的定义。 然后,如果尝试将main.oother.o链接到单个可执行文件中,则会出现链接器错误,指出int foo被定义了两次。

要正确实现此操作,您需要在头文件中声明变量为extern int foo。 然后,在一个(且仅一个)源文件中,您需要定义变量为int foo


所以在当前的项目中,我有一些C和cpp文件。C文件包括foo.h,其中包含我上面提到的main.h。cpp文件也是如此,除了foo.h被包含在extern "C"块中。当我将我的cpp文件添加到此项目中,并在extern C块中包含foo.h时,链接器会抛出LNK2005错误。为什么我的添加会导致这些链接器错误? - Jesavino
@Jesavino,这个回答解决了你发表的问题吗? - Drew Dormann
是的,它确实有用。我仍然希望得到后续答案,但我已经接受了它。 - Jesavino

4

真正的定义(不是 extern)不应该放在头文件中。

如果您希望在不同的 cpp 中使用一个全局变量,需要进行两个步骤:在一个 cpp 文件中进行定义,在头文件中进行外部声明。

例如:

// global.h
extern int foo;

and

// global.cpp
int foo;

然后在任何需要foo的文件中:

#include "global.h"

当然,global.cpp 必须是项目的一部分(与其他文件一起编译)。

1
你所做的在 C++ 中是完全合法的,只要没有多个文件定义了相同的变量。
变量或函数可能在另一个源文件中定义,或者在同一个文件中稍后定义。文件范围内变量和函数的声明默认为外部声明。
通常,我们在某个其他文件中声明全局变量的时候使用 extern
这就像一个初始化为 0 的全局变量一样好。

1
可能不会有多个文件定义变量,但可能会有多个翻译单元定义它(通过相同的头文件)。在头文件中放置定义是合法的(虽然通常不是一个好主意),但仍然可能会从使用该头文件的不同翻译单元中得到额外的定义。 - Dmitri
如果将定义放在#ifdef块内,即使头文件被多次包含,也会防止多重定义,对吗? - Marshall Eubanks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接