本文总结在C和C++中,extern用法的含义,内容来自网络,有部分修改。
在说明extern的作用之前,先说明一下声明(declaration)与定义(definition)的概念。
声明表示一个标识符(变量和函数)在程序的某个地方出现过,然而并不会为变量/函数分配内存。通过声明能知道标识符的类型,如果源文件中没有该变量/函数的定义,在汇编(gcc -c)时生成的可重定位目标文件(.o文件)中,会为该变量/函数预留连接时所需的“接口”。因此,同一声明在源文件中能出现多次。
与声明相比,定义标识符的过程中,已经为标识符分配了内存。同时,定义在代码中只能出现一次。简而言之,声明不分配内存,能在代码中出现多次;定义分配内存,在代码中只出现一次。
在c和c++中,extern被用来修饰标识符(变量和函数)的链接属性。被extern修饰的声明,表示该符号对其他模块(源文件)可见,同时也表示该符号可以从其他模块找到定义。这种对标识符链接属性的修饰是双向的,既可以被其它模块看见,也可以看见其它模块。
在默认情况下,函数外的标识符的链接属性默认是extern的。如果想让对标识符进行隔离,即不能在模块间链接标识符,则需要在标识符的前面添加static。
对于变量的声明,比函数要复杂一些。没有显式extern的变量声明时,变量进行默认的初始化(分配内存),变量的定义和声明是同时完成的;当进行显式的extern声明时,变量不能默认初始化。
extern除了改变标识符的链接属性之外,在c++中,还有特殊的用法。extern "C" 能够使c++中使用c语言的代码。
被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y); 该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(名字根据C++编译器而又不同风格,基本上人类看着都是胡乱的字符串)。这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。
所以,可以用一句话概括extern “C”这个声明的真实目的:解决名字匹配问题,实现C++与C的混合编程。
函数中的extern申明:
函数中出现extern申明,申明此变量为全局的,而且可以是在别的文件中定义的!
在函数中申明的好处是,控制这个全局变量在当前文件中的可见范围。