C++ extern
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编 译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。
这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。
由于C、C++编译器对函数的编译处理是不完全相同的,尤其对于C++来说,支持函数的重载,编译后的函数一般是以函数名和形参类型来命名的。
例如函数void fun(int, int),编译后的可能是(不同编译器结果不同)_fun_int_int(不同编译器可能不同,但都采用了类似的机制,用函数名和参数类型来命名编译后的函数名);而C语言没有类似的重载机制,一般是利用函数名来指明编译后的函数名的,对应上面的函数可能会是_fun这样的名字。
主要用在下面的情况:
1、C++代码调用C语言代码
2、在C++的头文件中使用
3、在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到
#ifndef __INCvxWorksh /*防止该头文件被重复引用*/ #define __INCvxWorksh
#ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的 extern "C"{ #endif /*…*/ //将这部分代码按照c语言来编译 #ifdef __cplusplus } #endif
#endif /*end of __INCvxWorksh*/
extern对应的关键字是static,static表明变量或者函数只能在本模块中使用,因此,被static修饰的变量或者函数不可能被extern C修饰。
被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的
// c.c #include <stdio.h> int main() { #ifdef __cplusplus printf("defined __cplusplus\n"); #else printf("undefined __cplusplus\n"); #endif return 0; }
使用gcc(g++编译的结果也一样,看来是c or c++是取决于文件的后缀名是.c还是.cpp)编译的结果如下
mutian@mutian:~/share$ gcc c.c mutian@mutian:~/share$ ./a.out undefined __cplusplus mutian@mutian:~/share$ cp c.c cplusplus.cpp mutian@mutian:~/share$ g++ cplusplus.cpp mutian@mutian:~/share$ ./a.out defined __cplusplus
现在再来看另一个例子
// add.h #ifndef _ADD_H_ #define _ADD_H_ #ifdef __cplusplus extern "C" { #endif int bhcnm(int); #ifdef __cplusplus } #endif #endif
// add.c
#include <stdio.h> int bhcnm(int value) { #ifdef __cplusplus printf("%s defined __cplusplus\n", __func__); #else printf("%s undefined __cplusplus\n", __func__); #endif return value + 1; }
我们可以看到add.c并没有包含add.h文件。gcc -c add.c 一样可以编译过。
add.h是给test.cpp使用的, 所以如果add.c里面的方法要给test.cpp使用的话,
那么最好是直接在add.h文件中声明该方法为extern方法,这样test.cpp包含add.h
头文件后就不需要再声明该方法为extern
显然add.c未必一定要包含add.h文件。
// test.cpp #include <stdio.h> #include "add.h" int main() { int a = bhcnm(10); printf("a:%d\n", a); #ifdef __cplusplus printf("%s defined __cplusplus\n", __func__); #else printf("%s undefined __cplusplus\n", __func__); #endif return 0; }
mutian@mutian:~/share$ gcc -c add.c
mutian@mutian:~/share$ gcc -c test.cpp
mutian@mutian:~/share$ gcc test.o add.o
mutian@mutian:~/share$ ./a.out
bhcnm undefined __cplusplus
a:11
main defined __cplusplus
显然对于C代码中是未定义__cplusplus,而c++中则定义了__cplusplus,add.h中的宏定义则可以兼容c或者c++编译模式
如果我们把add.h修改成这个样子,也就是不声明为extern "C"
// add.h #ifndef _ADD_H_ #define _ADD_H_ int bhcnm(int); #endif
mutian@mutian:~/share$ gcc test.o add.o
test.o: In function `main':
test.cpp:(.text+0xe): undefined reference to `bhcnm(int)'
collect2: ld returned 1 exit status
编译的时候就发现找不到这个方法的定义
如果声明为extern "C",那么C++中调用的这个函数的地方就按照c的方式来对符号名(即函数名或者变量名,这里是函数)进行修饰。

浙公网安备 33010602011771号