外部变量的问题

时间:2010-05-24 17:16:36

标签: c++ variables extern

我有2个cpp文件&头文件,我已经包含在两个cpp文件中。就像这样:

abc.h

extern uint32_t key;

a.cpp

#include "abc.h"
uint32_t key;
int main
{
.............
}

b.cpp

#include "abc.h"

int main
{
printf("Key: %.8x\n", key);
.............
}

现在当我编译a.cpp时,没有错误。但是当我编译b.cpp时它会给出错误 “对'key'的未定义引用”。请帮助我在此代码中找到问题。

6 个答案:

答案 0 :(得分:9)

要共享变量,通常会有以下内容:

// A.h
extern int key;
void show();

//a.cpp
#include "a.h"

int main() { 
    key = 1;
    show();
};

// b.cpp
#include "a.h"
#include <iostream>

int key;

void show() { std::cout << "Key = " << key; }

有几点不在这里。首先,将extern声明放在标题中,并将其包含在 all 中使用该变量的文件中。在一个且仅一个文件中定义变量(不包含extern)。只有一个文件应包含名为main的函数。

编辑:为了构建它,你自己编译每个文件,但你必须链接这两个文件。例如,使用gcc可以执行以下操作:

gcc -c a.c
gcc -c b.c
gcc a.o b.o

第一个编译(但没有链接)a.c.第二个实际上与bc相同。第三个实际上将两者链接在一起并生成可以执行的二进制图像(传统上命名为a.out,但是,例如,在Windows上,这通常更改为a.exe)。

答案 1 :(得分:3)

问题正是错误信息所说的。 Abc.h 声明变量,但它不定义它。 a.cpp中的行定义它。也就是说,a.cp​​p是变量的物理存储出现的地方。 b.cpp中没有这样的行,所以当你尝试编译那个程序时,链接器没有为该变量定义任何存储。

如果你在标题中省略了“extern”说明符,那么b.cpp编译得很好,但a.cpp可能会给出关于多个定义的错误。

当您在单个程序中有多个源文件时,“extern”说明符会发挥更大的作用。在这种情况下,它们可能都包含abc.h,但没有“extern”,每个编译的目标文件都有自己的相同变量的独立定义。链接器通常不知道该怎么做,并且可能会抱怨,尽管我认为不需要这样做。修复是使用“extern”,因此每个编译的文件文件只有声明。然后你选择一个源文件来放置定义。你可能把它放在abc.cpp中,因为声明在abc.h中。

答案 2 :(得分:2)

您正在编译两个单独的程序。一个人无法引用另一个变量。 extern关键字用于引用来自链接的同一可执行文件的另一个目标文件中的一个目标文件中的符号。

答案 3 :(得分:1)

我猜您收到了链接错误?在链接b时你需要包含a.o,不过如果你真的在a和b中都有“main”,那将无效。您将需要生成声明密钥的c.cpp,并将c.o链接到a.exe和b.exe。

答案 4 :(得分:1)

头文件中的行是声明;它告诉编译器变量存在,但不为它分配任何空间。从一个或多个源文件构建程序时,其中一个必须还包含定义

在您的情况下,您在a.cpp中有一个定义,因此包含构建程序所需的所有内容。 b.cpp没有定义,因此无法链接。

有两种解决方案。将定义从a.cpp复制到b.cpp,或者将其移动到第三个源文件,并在构建两个程序时将其包含在源列表中。

答案 5 :(得分:0)

a.cppb.cpp都定义了main()个函数,并且您只能为每个程序定义一个main()。所以,我假设你要做的是在两个程序之间共享一个头文件。在这种情况下,请将行添加到b.cpp以定义key并重新编译:

uint32_t key;

这不是使用头文件的常规方法。相反,您编写函数以key作为参数。这样做会设置一个全局变量,这通常是不受欢迎的。

extern几乎总是用来设置一个全局变量(我无法想到使用extern的任何其他原因)。但是如果你想按照它通常使用的方式使用extern - 而不考虑它是否应该被使用 - 你会做以下事情:

  • 从两个文件中的一个文件中删除main()功能,出于此答案的目的,我们会将其从b.cpp中删除。
  • 使用以下两行来编译和链接您的程序(假设gcc):

    gcc -c -o b.o b.cpp

    gcc a.cpp b.o

-c的{​​{1}}选项(第一行)显示“compile only, do not link。”这是确定是否定义了所有变量的链接步骤,并且在编译gcc时未定义它们,但是在编译b.cpp(第二行)时定义它们。