我正在尝试弄清楚,如果某个程序中出现以下情况会发生什么:
extern int x;
void foo(){...}
void bar(){...}
void main(){
foo();
bar();
}
int x=0;
那么应该发生什么?为什么允许有两个同名的变量?它们不同吗?
它们不是“两个”变量。它们是同一个。
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 获取示例。
完全没问题。这个
extern int x;
只声明了类型为int的变量x,而extern则明确表示它将在另一个位置被定义。
在您的情况下,就在几行代码之后。
int x = 0;
这里有一个关于extern的更多信息链接 -> http://en.cppreference.com/w/cpp/language/storage_duration
extern只允许在变量和函数的声明中使用(不包括类成员或函数参数)。它指定外部链接,且从技术上来说并不影响存储期限,但是不能用于自动存储期限对象的定义,因此所有extern对象都具有静态或线程存储期。 此外,一个使用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
文件中,这两个文件将在构建过程中链接在一起。
extern
在头文件中。 - M.M
int x; int x; int x = 3; extern int x;
即使使用GCC设置了非常挑剔的选项,它也能够编译通过。将extern
行移到开头,然后用clang -Weverything
命令也可以编译通过。前两个int x;
是尝试性定义。而int x = 3;
则是非尝试性(明确的)定义。你不能重复这样做,或者使用不同的初始化器。如果在文件结束时没有确定的定义,那么int x;
将被转换为一个确定的定义。 - Jonathan Leffler