eg.
#ifdef __cplusplus
extern "C" {
#endif
/*...*/
#ifdef __cplusplus
}

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

  被extern "C"限定的函数或变量是extern类型的;

  extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。

被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;

 作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );


  该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。

如果这个函数在C中编译成库,目标文件中函数名为_func,当这个函数中C++中被调用时,C++的编译器就会到目标文件中寻找_foo_int_int,结果找不到,出错。
所以为了防止这种问题,在C++调用时,将函数声明前加个extern "C" 告诉C++的编译器,不要对名字再进修饰,而直接去找_func。

同样在C++中编译的函数,如果想让C来使用,通常也加上extern "C"在编译时将函数名按C的风格进行修饰。

.可以包含头文件,相当于头文件中的声明都加了extern "C"
  extern "C"
 {
   #i nclude <cmath>
 }


   extern "C"
  {
     double sqrt(double);
     int min(int, int);
 }


接下来,我们来看下#ifdef _cplusplus/#endif _cplusplus的作用。很明显#ifdef/#endif、#ifndef/#endif用于条件编译,#ifdef _cplusplus/#endif _cplusplus——表示如果定义了宏_cplusplus,就执行#ifdef/#endif之间的语句,否则就不执行。

在这里为什么需要#ifdef _cplusplus/#endif _cplusplus呢?因为C语言中不支持extern "C"声明,如果你明白extern "C"的作用就知道在C中也没有必要这样做,这就是条件编译的作用!在.c文件中包含了extern "C"时会出现编译时错误。

C++中调用C的代码

假设一个C的头文件cHeader.h中包含一个函数print(int i),为了在C++中能够调用它,必须要加上extern关键字(原因在extern关键字那节已经介绍)。它的代码如下:

1
2
3
4
5
6
#ifndef C_HEADER
#define C_HEADER
externvoidprint(inti);
#endif C_HEADER

相对应的实现文件为cHeader.c的代码为:

1
2
3
4
5
6
#include <stdio.h>
#include "cHeader.h"
voidprint(inti)
{
printf("cHeader %d\n",i);
}

现在C++的代码文件C++.cpp中引用C中的print(int i)函数:

1
2
3
4
5
6
7
8
9
extern"C"{
#include "cHeader.h"
}
intmain(intargc,char** argv)
{
print(3);
return0;
}

------------------------------------

extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。