0%

C++中的extern C

前言

之前在华为实习的时候,经常看见以下语句:

1
2
3
4
5
6
7
#ifdef __cplusplus 
extern "C" {
#endif
//一段代码
#ifdef __cplusplus
}
#endif

当时不理解这是什么意思,但是,有时候,某个函数不在这里面,在编译的时候会失败。

前几天问了以下邹建伟老师,得到了答案。

老师的解释

extern “C”的主要作用就是提示C++编译器按C语言语义编译某些按C语言语义书写的函数代码,即加上extern “C”后,会指示C++编译器对“{}”内声明的函数,按C语言语义进行编译,而不是按C++语义进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。这样做的目的是如果一个程序主要按C++语义来编写,但是需要调用之前由C语言语义编写的函数代码(最可能的情况是要调用以前由C语言实现的函数库中的函数),就要使用这个语句。例如:

1
2
3
extern "C" {
void foo();
}

就是提示C++编译器,foo()是一个在外部模块实现的函数,且是以C语言事先实现的(一般是指某个函数库中的函数),这样编译器就不需要在本模块中找foo的代码(不使用extern声明的话,编译器会报错),在linker链接时,结合头文件的声明,可以把foo函数在函数库中的代码链接到可执行文件映像中。

综上所述

extern "C" {}的作用就是让编译器在编译这一块代码块时,使用C的编译器,而不是C++编译器。

相关资料

转载自:http://blog.csdn.net/xl_lbj/article/details/12510309

时常在cpp的代码之中看到这样的代码:

1
2
3
4
5
6
7
#ifdef __cplusplus 
extern "C" {
#endif
//一段代码
#ifdef __cplusplus
}
#endif

这样的代码到底是什么意思呢?首先,__cplusplus是cpp中的自定义宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern “C”{和}处理其中的代码。

要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起。

在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等。

而在C中,只是简单的函数名字而已,不会加入其他的信息。

也就是说:C++和C对产生的函数名字的处理是不一样的。

目的就是主要实现C与C++的相互调用问题。

c.h的实现

1
2
3
4
5
6
7
8
9
10
#ifndef _c_h_
#define _c_h_
#ifdef __cplusplus
extern "C" {
#endif
void C_fun();
#ifdef __cplusplus
}
#endif
#endif

c.c的实现

1
2
3
4
#include "c.h"
void C_fun()
{
}

在cpp.cpp中调用c.c中的C_test()

cpp.cpp的实现

1
2
3
4
5
#include "c.h"
int main()
{
C_fun()
}

其中__cplusplus是C++编译器的保留宏定义.就是说C++编译器认为这个宏已经定义了。

所以关键是extern “C” {}

extern “C”是告诉C++编译器件括号里的东东(比如函数)是按照C的obj文件格式编译的,要连接的话按照C的命名规则去找.

那么C中是如何调用C++中的函数cpp_fun()呢?
因为先有C后有C++, 所以只能从C++的代码中考虑了.
加入C++中的函数或变量有可能被C中的文件调用,则应该这样写,也是用extern “C”{}
不过是代码中要加,头文件也要加,因为可能是C++中也调用

cpp.h的实现

1
2
3
4
5
6
7
8
9
10
#ifndef _c_h_
#define _c_h_
#ifdef __cplusplus
extern "C" {
#endif
void CPP_fun();
#ifdef __cplusplus
}
#endif
#endif

cpp.cpp的实现

1
2
3
4
5
extern "C" {    //告诉C+++编译器,扩号里按照C的命名规则编译
void CPP_fun()
{
.....
}

C和C++对函数的处理方式是不同的。
extern “C”是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern “C”来说明。

__cplusplus是C++编译器的保留宏定义
extern “C” { …… } //告诉C+++编译器,扩号里按照C的命名规则进行编译