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的方式来对符号名(即函数名或者变量名,这里是函数)进行修饰。

posted @ 2015-04-15 09:58  牧 天  阅读(277)  评论(0)    收藏  举报