在C中使用“extern”存储类说明符

时间:2009-11-24 04:54:06

标签: c++ c extern

以下extern说明符的示例用法如何表现。

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

extern int x;

编译和链接这些文件会发生什么?

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

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

5 个答案:

答案 0 :(得分:6)

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

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

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

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

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

所以,回答你原来的问题,你是对的 - 编译会成功,但由于变量x与外部链接的多重定义(特别是来自翻译单元{{1),链接会失败}和one.c)。

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

答案 1 :(得分: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;

现在,您可以从文件x明确地引用文件one.c中的x或文件two.c中的three.c

然而,这可能比它的价值更多。也许你应该为你的全局变量提出更具描述性的名称,而不是用理论方法来绕过C的单个全局命名空间。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

您可能会对this question的答案感兴趣。

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

答案 4 :(得分:0)

请记住,你不能extern一个全局静态变量.. !!