extern "C"的小结 来自《程序员的自我修养》
-
C++为了与C兼容,C++可以使用关键字extern "C"来声明或者定义一个C符号:
extern "C"{ int func(int); int var; }``` C\+\+会将extern "C"的大括号内的代码当做C语言代码**(.c文件)**处理,亦即在大括号中C\+\+的名称修饰机制将不起作用,不同的编译器有不同的名称修饰方法: 1.如果是VC++平台,上述代码中的fun和var会被修饰(名称修饰)为_func和_var; 2.但是如果是linux下的gcc编译器,前面的_也会被去掉,extern "C"里面的符号就是修饰后符号(为func和var)。 【补充】gcc编译.c文件,因为是按照c方式编译,所以函数名不变;gcc编译.cpp文件,g\+\+编译.c文件,g\+\+编译.cpp文件,因为是按照c\+\+方式编译,所以函数名才会加上了附加信息。(当前编译器编译出来的目标文件和库文件(目标文件)应该是同样的编译器编译出来的) ps:单独声明某个函数或者是变量是C的符号,可以直接
extern "C" int func(int);
extern "C"带来的问题
我们经常遇到这样的情况:有些头文件声明了一些C语言的函数和变量,但是这个头文件可能被C语言或者是C++语言包含。例如:
对于函数 void memset (void , int, size_t) 而言,如果不使用extern "C"**,考虑一以下两种情况:
1.在C语言程序包含string.h的时候,如果用到了memset这个函数,编译器会进行正确的函数名称修饰memset(C语言的名称修饰,前面加),也可以正确的连接到C语言库中的memset符号。
2.在C++程序中包含了memset函数,编译器编译器会认为这是一个C++函数,函数名就会被修饰为_Z6memsetPvii(C++的名称修饰可自行了解),这样的话,链接器就没办法在C语言的库中找到对应的符号地址。此时就必须使用extern "C"。-
C与C++的兼容问题的实现
方法是使用C++的宏__cplusplus#ifdef __cplusplus extern "C" { #endif // 代码 #ifdef __cplusplus } #endif
含义是,如果是C++代码,那么memset会在extern "C"中被声明,如果是C代码就直接声明。