extern
是 C/C++
语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
注意,语句 extern int a;
仅仅是对变量的声明,其并不是在定义变量a
,声明变量并未为 a
分配内存空间。定义语句形式为 int a;
,变量 a
在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
在引用全局变量和函数之前,必须要有这个变量或者函数的声明(或者定义)。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字 extern
声明。
与 extern
对应的关键字是 static
,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被 extern "C" 修饰。
作为一种面向对象的语言, C++
支持函数重载,而过程式语言 C
则不支持。所以,函数被 C++
编译后在符号库中的名字与 C
语言的有所不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被 C
编译器编译后在符号库中的名字为 _foo
,而 C++
编译器则会产生像 _foo_int_int
之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为 mangled name
)。 _foo_int_int
这样的名字包含了函数名、函数参数数量及类型信息, C++
就是靠这种机制来实现函数重载的。例如,在 C++
中,函数 void foo( int x, int y )
与 void foo( int x, float y )
编译生成的符号是不相同的,后者为 _foo_int_float
。
所以C和C++之间直接相互调用函数会导致链接错误。本质原因是C语言和C++编译器生成的符号名是不同的。
使用extern C声明之后,编译器将采用C语言的编译连接方式,不会对符号名称进行特殊处理