转自大牛的解析(非常具体详细)http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html

我做个简单的标注方便以后自己查看:

在用C++的项目源码中,经常会不可避免的会看到下面的代码:

  1. #ifdef __cplusplus //采用c++,自动定义__cplusplus的宏
  2. extern "C" {
  3. #endif
  4.  
  5. /*...*/
  6.  
  7. #ifdef __cplusplus
  8. }
  9. #endif

extern "C" 是为了实现C++与C及其它语言的混合编程,由于C++支持函数重载,同名函数在编译阶段会根据参数特征表的不同命名不同的全局名称,如:

C++中  void func(int,int) 命名为 _func_int_int

而C方式编译后命名为 _func

3.2、C的编译和连接

C语言中并没有重载和类这些特性,故并不像C++那样print(int i),会被编译为_print_int,而是直接编译为_print等。因此如果直接在C++中调用C的函数会失败,因为连接是调用C中的print(3)时,它会去找_print_int(3)。因此extern "C"的作用就体现出来了。

3.3、C++中调用C的代码

假设一个C的头文件cHeader.h中包含一个函数print(int i),函数前面的extern可加可不加,函数默认即为外部链接的(其他文件中声明引用也不需要要extern关键字,原作者这里有误)。它的代码如下:

  1. #ifndef C_HEADER
  2. #define C_HEADER
  3.  
  4. extern void print(int i);
  5.  
  6. #endif C_HEADER

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

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

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

  1. extern "C"{ //即告诉编译器这里面是按C语言编译和链接的,调用这里的函数也按C的方式来进行
  2. #include "cHeader.h"
  3. }
  4.  
  5. int main(int argc,char** argv)
  6. {
  7. print();
  8. return ;
  9. }

执行程序输出:

3.4、C中调用C++的代码

现在换成在C中调用C++的代码,这与在C++中调用C的代码有所不同。如下在cppHeader.h头文件中定义了下面的代码:

  1. #ifndef CPP_HEADER
  2. #define CPP_HEADER
  3.  
  4. extern "C" void print(int i);
  5.  
  6. #endif CPP_HEADER

相应的实现文件cppHeader.cpp文件中代码如下:

  1. #include "cppHeader.h"
  2.  
  3. #include <iostream>
  4. using namespace std;
  5. void print(int i)
  6. {
  7. cout<<"cppHeader "<<i<<endl;
  8. }

在C的代码文件c.c中调用print函数:

  1. extern void print(int i);
  2. int main(int argc,char** argv)
  3. {
  4. print();
  5. return ;
  6. }

注意在C的代码文件中直接#include "cppHeader.h"头文件,编译出错。而且如果不加extern int print(int i)编译也会出错。

extern "C"指令非常有用,因为C和C++的近亲关系。注意:extern "C"指令中的C,表示的一种编译和连接规约,而不是一种语言。C表示符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。

还有要说明的是,extern "C"指令仅指定编译和连接规约,但不影响语义。例如在函数声明中,指定了extern "C",仍然要遵守C++的类型检测、参数转换规则。

再看下面的一个例子,为了声明一个变量而不是定义一个变量,你必须在声明时指定extern关键字,但是当你又加上了"C",它不会改变语义,但是会改变它的编译和连接方式。

如果你有很多语言要加上extern "C",你可以将它们放到extern "C"{ }中。

PS: extern 用于变量和函数

之于变量

player.h:

          //全局命名空间

          int a=20;//全局变量默认是extern的

static int b=10;//定义内部链接的变量

xxx.cpp:

extern int a;// 只声明,不能重复定义

之于函数

函数默认都是外部链接的(如库文件定义的函数也都没有加extern关键字)

player.h:

void foo(){.....}

xxx.cpp:

#include "player.h";

//包含头文件后,直接用就行了

extern "C"解析的更多相关文章

  1. C/C++中extern关键字解析

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  2. extern "c"用法解析

    转自: extern "c"用法解析 - 简书 引言 C++保留了一部分过程式语言的特点,因而它可以定义不属于任何类的全局变量和函数.但是,C++毕竟是一种面向对象的程序设计语言, ...

  3. 探索C++的秘密之详解extern "C",这就是为什么很多.lib被我们正确调用确总是无法解析的。

    (转载,绝对的有用) lib被我们正确调用确总是无法解析.这是C++编译和C编译的区别 时常在cpp的代码之中看到这样的代码: #ifdef __cplusplus extern "C&qu ...

  4. extern "C" 用法解析

    extern "c"用法解析 作者 作者Jason Ding ,链接http://www.jianshu.com/p/5d2eeeb93590 引言 C++保留了一部分过程式语言的 ...

  5. 解析“extern”

    解析“extern” 1. 声明外部变量 现代编译器一般採用按文件编译的方式,因此在编译时,各个文件里定义的全局变量是 互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部.以下举一个简单的 ...

  6. DLL模块:extern "C"的简单解析

    1.揭密extern "C" extern "C"包含双重含义,从字面上即可得到:首先,被它修饰的目标是 "extern”的:其次,被它修饰的目标是 ...

  7. C/C++之extern "C"的用法解析

    extern "C"的用法解析 http://blog.sina.com.cn/u/494a1ebc010004g5 C++中extern “C”含义深层探索 1.引言 C++语言 ...

  8. ZT extern "C"的用法解析

    extern "C"的用法解析 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同. ...

  9. (转)探索C++的秘密之详解extern "C",这就是为什么很多.lib被我们正确调用确总是无法解析的。

    (转载,绝对的有用) lib被我们正确调用确总是无法解析.这是C++编译和C编译的区别 时常在cpp的代码之中看到这样的代码: #ifdef __cplusplus extern "C&qu ...

随机推荐

  1. V4L2学习(四)VIVI分析

    vivi 相对于后面要分析的 usb 摄像头驱动程序,它没有真正的硬件相关层的操作,也就是说抛开了复杂的 usb 层的相关知识,便于理解 V4L2 驱动框架,侧重于驱动和应用的交互. 前面我们提到,V ...

  2. 洛谷P1424小鱼的航程改进版

    题目链接https://www.luogu.org/problemnew/show/P1424

  3. Helloworld 在jvm 内存图

    HelloWorld.java源码如下:   public class HelloWorld { public static void main(String[] args) { String s ; ...

  4. 免费生成https证书以及配置

    http升级到https需要在nginx的配置中加入证书信息,查询资料后确定生成证书两种方案   第一种:自签名证书,然后开启 CloudFlare 的 CDN 服务   //确定是否安装openss ...

  5. Win7系统安装MySQL5.5.21图解

    Win7系统安装MySQL5.5.21图解 大家都知道MySQL是一款中.小型关系型数据库管理系统,很具有实用性,对于我们学习很多技术都有帮助,前几天我分别装了SQL Server 2008和Orac ...

  6. android 内存说明

    MemoryInfo的Field如下 dalvikPrivateDirty: The private dirty pages used by dalvik. dalvikPss :The propor ...

  7. PHP 删除 url 中的 query string

    function removeQueryStringFromUrl($url) { if (substr($url,0,4) =="http") { $urlPartsArray ...

  8. 【数据结构与算法】Fibonacci Sequence

    学计算机的对 Fibonacci 都并不陌生,在课堂上一讲到递归几乎都会提到 Fibonacci 数列.不久前,我对 Fibonacci 产生了一些兴趣,就在这里把自己的想法给记录下来. 递推公式: ...

  9. Linux下c++使用pthread库

    pthread 库是纯c库,没有类指针的概念,当想phread_create中传递类成员函数时,就会报错,这里针对这种情况,对线程创建做了必要封装,较为简单,继承类,实现run接口,然后使用start ...

  10. sql server 韩文查询匹配失败

    在SQL Server 中查询韩文信息时,没有匹配到对应的信息,检查程序后发现字段类型是nvarchar类型的没有问题, 打开存储过程后找到问题了:原来是拼接后的查询语句存储在一个varchar变量中 ...