1

以下 extern specifer 的示例用法如何表现。

我们在文件 one.c 和 two.c 中都有一个全局变量 int x 我们想在 three.c 中使用它们,所以在 three.c 中声明这个变量为

extern int x;

当我们编译和链接这些文件时会发生什么?

我的回答是:所有这些文件的编译都应该成功,但是链接器应该在链接时标记一个错误,因为 x.xml 的多个声明。C++ 中的行为会有什么不同吗?

这些是在 C 和 C++ 中同时从两个文件中引用 int x (在三个.c 中)的任何方式。在 C++ 中,我想我们可以使用命名空间来实现这一点。对?

4

5 回答 5

6

默认情况下,全局变量具有外部链接,这意味着它们可以被其他源文件(或“翻译单元”)使用。如果您改为使用static关键字声明全局变量,它们将具有内部链接,这意味着它们将不能被其他源文件使用。

对于带有外部链接的变量,不能有多个同名变量,否则链接器会报错。但是,您可以有两个具有相同名称的变量,只要至少一个具有内部链接,当然您不能在同一个源文件中同时引用它们。

extern声明只是对编译器说“这是在另一个翻译单元中定义的具有外部链接的某个变量的名称”,允许您引用该变量。

C++ 完全一样,只是增加了命名空间。如果将全局变量放在命名空间内,那么它们可以具有相同的名称而不会出现链接器错误,前提是它们位于不同的命名空间中。当然,所有对这些变量的引用必须要么引用全名namespace::var_name,要么使用using声明来建立本地命名空间上下文。

C++ 也有匿名命名空间,这完全等同于static在 C 中为全局变量使用关键字:在匿名命名空间内声明的所有变量和函数都有内部链接。

因此,要回答您的原始问题,您是对的 - 编译会成功,但链接会失败,因为x具有外部链接的变量的多个定义(特别是来自翻译单元one.ctwo.c)。

three.c,没有办法同时引用这两个变量x。您需要x在一个或两个模块中重命名,或者切换到 C++ 并在命名空间中至少x放置一个。

于 2009-11-24T05:08:21.970 回答
1

在 C 中,您可以这样做:

// one.c
static int x;
int *one_x = &x;

// two.c
static int x;
int *two_x = &x;

// three.c
extern int *one_x;
extern int *two_x;

现在您可以明确地引用文件中的xin 文件one.cxintwo.c文件three.c

然而,这可能比它的价值多一点努力。也许您应该为全局变量想出更具描述性的名称,而不是玩弄理论方法来规避 C 的单一全局命名空间。

于 2009-11-24T05:09:45.930 回答
0

为避免生成重复符号,您应该extern int x;在单个头文件(.h 文件)中声明,然后让所有将使用 x该头文件的 .c 文件,并在其中一个#include.c 文件中定义或初始化。int x;

于 2009-11-24T04:57:01.180 回答
0

您可能会对这个问题的答案感兴趣。

摘要:链接器可能会也可能不会链接文件失败。这取决于变量的初始化。如果变量在不同的文件中有不同的初始化,它肯定会失败。

于 2009-11-24T05:03:55.177 回答
0

请记住,您不能 extern 全局静态变量.. !!

于 2009-11-24T07:49:19.587 回答