摘自:http://blog.csdn.net/fxjtoday/article/details/6021845
如果想明白为什么需要extern, 需要从编译和链接讨论起,
现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。但是到了链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,会报错. 因此,各个文件中定义的全局变量名不可相同。
//A.cpp
int i;
void main()
{
}
//B.cpp
int i;
所以上面两个文件编译是没有问题的, 但是到了链接就会报重名错误
如果此时A.cpp里面要用到, B.cpp中定义的i, 应该怎么办?
那么既然上面说了重复定义出错, 那就把A.cpp中的"int i;"定义直接去掉是否可以
看起来好像可以的, 因为全局变量的作用域是整个源程序, 这边也许是很多人会产生疑问的地方, 既然全局变量和全局函数的作用域是整个源程序的, 为什么在其他的文件里面使用一定要先声明(这样的声明往往在.h文件中, 并在使用处include该.h, 记住include就是copy, 之所以要使用.h, 而不是直接写在.c中, 只是为了保证易维护性, 最终编译器会自动将.h copy到每个.c中)
答案就在编译阶段, 过程是先编译后链接, 而在编译时只能知道本文件的内容, 编译器并不能预见到你这个变量或函数在其他文件里面被定义过. 只有到了链接阶段编译器产能看到其他的文件.
所以如果不事先声明, 那么在编译阶段一定会报错找不到该变量或函数.此时就需要使用extern来声明变量。
extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”
多说一句, 在声明变量是必须要加extern, 而在声明函数时却不需要, 为什么
上面说了, 声明只是简单的告诉编译器, 这个东西在其他地方定义过了, 你不用管了, 所以编译器不会为声明分配空间, 或做其他操作, 这和定义是有本质区别的, 必须要正确区分
对于变量必须用extern才能区分定义和声明, 因为这是变量定义和声明的唯一区别
而函数不需要extern也能区分处定义和声明, 有实现就是定义, 没有就是声明, 所以不需要再加extern
这就是c的简洁之处, 不需要的就别写
再多说一句, 在c中, 全局变量和函数都是默认对外可见的, 如果想变成仅当前文件可见, 必须加上static.
对于函数, 默认和加上extern是等价的, 都是表示对外可见
但是对于变量, 却不一样, 加上extern就变成声明了, 所以不能给定义加上extern
所以对于extern有如下说法,
用于变量,声明该变量在其它地方定义;
用于函数定义, 表示全局可见(属于冗余的)