前段时间在萧大的技术社区http://cocode.cc/上看到一个问题(http://cocode.cc/t/topic/4213)提问者是个初学者,问的是C语言中关于变量的外部链接的问题,其实就是extern关键字的用法,回答了一下小白的问题,同时在回答问题的过程中自己也学到了新的东西,便有了把这个答案分享出来的打算。
首先我们来看看extern的定义:
这是维基百科上的定义,extern修饰的关键字,具有文件外部链接,但是声明extern变量时,编译器并不会给这个变量分配内存,在另外的文件中定义这个文件时才会为其分配内存,一旦声明了extern关键字,对编译器来意味着:
- 这个变量声明(即数据类型和变量名,但是编译器并没有分配内存)
- 这个变量的定义在其他文件中(在定义变量的文件中编译器才会为其分配内存)
这看上去很奇怪,但是仔细想一想,这和函数的前置声明以及类的前置声明有异曲同工之处,在我看来这是为了将声明与实现分离,便于文件之间的数据共享。
下面来看看extern的用法:
extern主要是为了解决在几个源文件共享同一个变量,在链接各个cpp文件时。当一个cpp文件在编译的过程中,若需要一个变量但是当前的作用域没有发现其定义,如果这个变量是extern修饰的,那么编译器会知道其定义在其他文件中,在obj文件的链接过程中会得到该变量的值。
![Uploading QQ截图20160415194053_267714.jpg . . .]
如果我们仅仅在头文件中声明了extern变量而为初始化它,那么会出现” undefined reference to ‘global_x’ ”的错误,在使用extern的关键字的时候要注意一下几点:
- extern变量可以声明多次,但是只能初始化一次,如下
-
extern变量的初始化需要在全局作用域中初始化,所以在局部作用域中不论是声明并初始化,或者声明与初始化分开都会导致编译器报错,如下:
一旦声明了extern变量,那么在程序链接的时候无论它初始化没有,都会查找extern的定义,如下:
这以上是extern的一些用法,我写代码的时候很少用到extern关键字,值得注意一点的是C语言中的函数原型是本身都具有外部链接的属性的,在C语言中extern关键字的存在改变了变量的链接属性,用extern关键字修饰的变量其定义将在别处,编译器的变量的解析将推迟到链接上,在实际中,对于函数来说extern将是没有必要的修饰,而在对变量的修饰中,最好将extern变量的声明放在头文件中,将变量的定义放在一个源文件中。
相关资料:
extern的定义(Wiki需要科学上网)
如何组织extern头文件和源文件(答主写的很用心,值得一看,我只看懂了一部分,捂脸。。。。)
Keep focus and have fun!