C语言中同名的外部变量和全局变量

4

我正在尝试弄清楚,如果某个程序中出现以下情况会发生什么:

extern int x;

void foo(){...}
void bar(){...}

void main(){
foo();
bar();
}
int x=0;

那么应该发生什么?为什么允许有两个同名的变量?它们不同吗?


2
尝试编译以下代码: int x; int x; int x = 3; extern int x; 即使使用GCC设置了非常挑剔的选项,它也能够编译通过。将extern行移到开头,然后用clang -Weverything命令也可以编译通过。前两个int x;是尝试性定义。而int x = 3;则是非尝试性(明确的)定义。你不能重复这样做,或者使用不同的初始化器。如果在文件结束时没有确定的定义,那么int x;将被转换为一个确定的定义。 - Jonathan Leffler
在文件作用域声明的变量,如果没有存储类别说明符,则具有与显式声明为“extern”的变量相同的存储类别和链接。也就是说,“extern”和“global”类型的变量之间没有区别。然而,在其他方面,存在或不存在“extern”可能会有所不同。 - John Bollinger
3个回答

7

它们不是“两个”变量。它们是同一个

extern int x;

x的声明。

以及。

int x=0;

提供了 x 的定义。这是完全正确和有效的。


你可以有多个声明,例如:

extern int x;
extern int x;

当你为同一标识符提供多个声明时,请注意规则有些复杂。详情请参见:6.2.2 标识符的链接。 可参考static declaration of m follows non-static declaration 获取示例。


3

完全没问题。这个

extern int x;

只声明了类型为int的变量x,而extern则明确表示它将在另一个位置被定义。

在您的情况下,就在几行代码之后。

int x = 0;

这里有一个关于extern的更多信息链接 -> http://en.cppreference.com/w/cpp/language/storage_duration

extern只允许在变量和函数的声明中使用(不包括类成员或函数参数)。它指定外部链接,且从技术上来说并不影响存储期限,但是不能用于自动存储期限对象的定义,因此所有extern对象都具有静态或线程存储期。 此外,一个使用extern并且没有初始化程序的变量声明不是定义


2
“extern”表示:“这个变量将来自其他地方。它并没有在此处声明,这个声明仅提供了通知,表明它是一个有效的名称。”
因此,本质上这段代码是:
extern int x;
// This is a valid name, but the variable will be defined "externally", eg, somewhere else.

[...] 

int x=0;
// OH!  Here is where the definition is.  Now we know where that "extern" variable came from.
// And we know that it starts with value 0.

在同一个文件中出现 extern 和定义是有些不寻常的。

更典型的情况是,定义在一个 .C 文件中,而 extern 在一个不同的 .C 文件中,这两个文件将在构建过程中链接在一起。


2
更典型的情况是extern在头文件中。 - M.M

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