引言
  在用C++的项目源码中,经常会不可避免的会看到下面的代码
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*...*/
  #ifdef __cplusplus
  }
  #endif
  它到底有什么用呢,你知道吗?而且这样的问题经常会出现在面试or笔试中。下面我从以下几个方面来介绍它:
  1、#ifdef _cplusplus/#endif _cplusplus及发散
  2、extern "C"
  2.1、extern关键字
  2.2、"C"
  2.3、小结extern "C"
  3、C和C++互相调用
  3.1、C++的编译和连接
  3.2、C的编译和连接
  3.3、C++中调用C的代码
  3.4、C中调用C++的代码
  4、C和C++混合调用特别之处函数指针
  1、#ifdef _cplusplus/#endif _cplusplus及发散
  在介绍extern "C"之前,我们来看下#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"时会出现编译时错误。
  既然说到了条件编译,我介绍它的一个重要应用——避免重复包含头文件。还记得腾讯笔试考过这个题目,给出类似下面的代码(下面是我近在研究的一个开源web服务器——Mongoose的头文件mongoose.h中的一段代码):
  #ifndef MONGOOSE_HEADER_INCLUDED
  #define    MONGOOSE_HEADER_INCLUDED
  #ifdef __cplusplus
  extern "C" {
  #endif /* __cplusplus */
  /*.................................
  * do something here
  *.................................
  */
  #ifdef __cplusplus
  }
  #endif /* __cplusplus */
  #endif /* MONGOOSE_HEADER_INCLUDED */
  然后叫你说明上面宏#ifndef/#endif的作用?为了解释一个问题,我们先来看两个事实:
  这个头文件mongoose.h可能在项目中被多个源文件包含(#include "mongoose.h"),而对于一个大型项目来说,这些冗余可能导致错误,因为一个头文件包含类定义或inline函数,在一个源文件中mongoose.h可能会被#include两次(如,a.h头文件包含了mongoose.h,而在b.c文件中#include a.h和mongoose.h)——这会出错(在同一个源文件中一个结构体、类等被定义了两次)。
  从逻辑观点和减少编译时间上,都要求去除这些冗余。然而让程序员去分析和去掉这些冗余,不仅枯燥且不太实际,重要的是有时候又需要这种冗余来保证各个模块的独立。