探索extern "C"

有一种说法是C++是另一种C语言,虽然在C++创建之初的初衷也是期望一个更好的C,但是C++中全局变量和函数所采用的编译和连接方式却与C语言不完全相同。这就会引起C++和C语言在处理全局变量和函数时所采用的不同方式,并且当这两种方式需要C++与C兼容时,就会引入一些平衡两种处理方式的另一种处理方法。

下面的代码段,在C程序里,应该经常可见

#ifdef __cplusplus
extern "C" {
#endif
。。。。。。
#ifdef __cplusplus
}
#endif
这是什么意思呢?

其实简单点说,在extern "C" 中修饰的变量和函数是按照C语言编译和连接的,下面会简单的说明不同编译方式对函数符号的影响。


一,extern "C"是什么意思

我们知道extern是C/C++语言中表明某个函数或者变量作用范围的关键字,就是一个变量在一个文件中被定义成全局变量,可以用这个关键字来在其它文件中引用,这个关键字是告诉编译器其所声明的符号(函数或变量)可以在这个模块中使用。这里要区分的是

int var_c;
表示变量的定义,而

extern int var_c;
不是变量的定义,而是一个声明,也就是说,并不会为变量var_c 分配内存空间,extern可以被多次使用同一个变量,但var_c的变量定义只能是被定义一次,如果多次定义,就会出现连接错误。

所以,extern "C" 表示 意思如下:

  1. 被修饰的符号(函数或变量)是extern类型的,这是C和C++都支持的关键字,并且都有表示模块之间变量引用的功能。
  2. "C"表示按C的方式编译和连接,为什么需要这样的处理,前面也说了,是为了在C++中对C处理全局变量和函数的方式兼容,那为什么需要兼容呢,他们不是一样的吗?当然有很多的地方还是不一样的,比如C++支持函数重载等等呢,是吧。

在C语言中经常出现的另一个修改函数关键字的作用是static,被这个关键字修饰的变量和函数就是只能在本模块中使用,这就是说如果两个模块中,需要出现同名函数,那么用static是可以实现的,这样会对另一个模块“隐藏”这个函数的定义。

二,对编译的影响

现在我们关心的是:在C++中,没有extern "C" 修饰和有extern "C" 修饰的符号有什么不同呢?
假设函数原型如下
int function(char *original);

这定义对C和C++都是一样的。

在被C++编译之后,我的编译器输出的符号为
client:00000000004006a8 R _IO_stdin_used
client:                 w _Jv_RegisterClasses
client:0000000000400578 T _Z8functionPc
client:00000000006007b8 d __CTOR_END__
client:00000000006007b0 d __CTOR_LIST__
可以看出function在编译器中的符号库中表示为_Z8functionPc,这会根据编译器的不同,而有所不同。

在被C编译之后,输出为:
client:00000000006008b8 b dtor_idx.6147
client:0000000000400470 t frame_dummy
client:00000000004004cd T function
client:0000000000400498 T main
发现了吧,C++ 和C编译器对同一个函数编译之后的符号是不一样的,C就是以函数名作为符号,而C++比较复杂,这也是为什么C++可以支持重载,而C不能支持的原因了。

现在我以C的方式编译,但是加上extern "C" 关键字,其编译之后的结果和C编译方式的结果是一样的。这里就不给出结果了。

你可能感兴趣的:(extern)