使用 extern 全局变量的正确方法是什么?
file a.cc
int a = 0;
file b.cc
#include "a.cc"
file main.cc
#include "b.cc"
extern int a;
int main() {
}
g++ -c a.cc
g++ -c b.cc
g++ main.cc a.o b.o
error: multiple definitions of a
我在这里做错了什么?
file a.cc
int a = 0;
file b.cc
#include "a.cc"
file main.cc
#include "b.cc"
extern int a;
int main() {
}
g++ -c a.cc
g++ -c b.cc
g++ main.cc a.o b.o
error: multiple definitions of a
What am I doing wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您包含
.cc
(或.cpp
)文件,这是错误的。不要那样做。您需要一个标头,并在其中放入extern int a;
:You include a
.cc
(or.cpp
) files, which is wrong. Do not do that. You need a header, and in that put theextern int a;
:您所做的正是链接器所说的:您正在提供“a”的多个定义。 a.cc 和 b.cc 都将变量“a”定义为具有外部链接的东西。
不要那样做!
不要#include 源文件。有时您确实想这样做,但有时您又想使用
goto
。You are doing exactly what the linker said: You are providing multiple definitions of 'a'. Both a.cc and b.cc are defining the variable 'a' as something with external linkage.
Don't do that!
Don't #include a source file. There are times when you do want to do that, but then again, there are times when you want to use
goto
.正如编译器告诉您的那样 - 您最终会在所有三个翻译单元中定义
a
!您想要相反的方式:重复包含的声明应该是外部的,并且只能有一个定义。例如:Exactly what the compiler tells you -- you end up defining
a
in all three translation units! You want it the other way around: The repeatedly included declaration should be extern, and there must only be one definition. For instance:使用 include 时,想象一下将所有文件放入一个文件中。这基本上就是编译器所看到的,因为所有内容都已在编译器阶段之前由预处理器包含。
所以你的 main.cc 开始看起来像这样。
编译器认为这没问题,因为没有初始化程序的 extern 只是一个声明,因此不会为其分配内存。然而,“int a”是一个定义,因此 main.o 包含为 a 分配内存的指令。
一旦链接它,链接器就会注意到 ao 和 bo 也已经定义了“a”。 “a”是因为这是它最初定义的地方,“b”是因为 b 包含具有定义的“a”。
要解决此问题,只需在 main.cc 中删除 #include "b.cc" 即可。事实上,完全删除 b.cc 是因为它没有任何意义。
如果您确实想正确执行此操作,请使用 extern int a 为“a”创建一个名为 ah 的单独标头。那么main.cc和b.cc就可以随意包含ah而不需要重新定义a。
When using the include, imagine placing all the files into one file. That is basically what the compiler sees because everything was included by the preprocessor before the compiler stage.
So your main.cc starts looking like this.
The compiler considers this okay because extern without an initializer is just a declaration so memory is not allocated for it. "int a" is a definition, however, so main.o includes instructions for allocating memory for a.
Once you link it, the linker notices that a.o and b.o already has "a" defined as well. "a" because this is where it was originally defined and "b" because b included "a" which had the definition.
To fix this, just take out #include "b.cc" in main.cc. In fact, take out b.cc entirely because there is no point in it.
If you really want to do this right, create a separate header for "a" called a.h with extern int a. Then main.cc and b.cc are free to include a.h without redefining a.