C和C++混合编程之 extern “C”的使用

首先要明白:

C++号称是C语言的超集,也确实,从语言的基本语法上,C++是包含所有C语言的语法的,而且C++为了兼容C,连C语言的标准库也被纳入到C++的标准库中,比如在C++中我们仍然可以使用<stdio.h>,它就是C++标准库的一部分(注意最好用新的标准<cstdio>,而不是老的<stdio>)。

但是,C++和C语言的编译器在有些地方还是有差别的。比如,C++是支持面向对象的特性(尽管C++被称为不彻底的面向对象语言),面向对象就要支持函数重载,而函数重载的实现和C++编译器是分不开的。

比如有:

int max(int a, int b);

double max(double a,double b);

这两个函数。

这两个函数同时存在,在C语言中是不可以的,因为C语言不支持重载,但是在C++中完全没有问题,因为C++是支持重载的。

那么为什么会这样呢?

这要从编译器的角度来看:

C编译器将int max(int a,int b)函数编译后,在符号库中的名字为_max(不同编译器可能有不同的形式)

C编译器将double max(double a,double b)函数编译后,在符号库中的名字也为_max。所以在C语言中,这两个函数是不能共存的的,编译时会提示错误。

但是C++编译器则不同

C++编译器将int max(int a, int b)编译后,在符号表中的名字为:

_max_int_int

而另一个则为_max_double_double。这两者并不冲突。

这也是C++支持函数重载的根本原因。不过,这也从另一面说明了:函数重载其实不是多态,顶多算是编译时多态。

在C++和C混合编程时:

在C++和C语言混合编程时,前面已经说过,C++的语法是完全包含C语言的语法的,所以不用担心语法上出现什么问题。出现问题的主要原因在编译和链接时。

思考这样一件事情:

我们在Linux下编程的时候,经常会用到内核的库,我们知道Linux内核使用C语言写的。如果这些库采用了C语言的编译器进行编译,而我们的程序是用C++开发的,要用C++进行编译,那么会出现什么问题?

比如:

我们有个.c文件p.c,内容如下:

#include <stdio.h>

void print(int a,int b)
{
printf("这里调用的是C语言的函数:%d,%d\n",a,b);
}

我们用gcc –c命令编译它,生成p.o文件

然后我们又p.h文件,里面是print函数的原型声明,如下:

void print(int a,int b);

我们又有main.cpp文件,内容如下

#include <iostream>

using namespace std;

#include "p.h"

int main()
{
cout<<"现在调用C语言函数\n";
print(,);
return ; }

这次我们用g++ -c进行编译,生成main.o文件

然后我们用g++链接两个.o文件,这时我们会发现,报错:

这时为什么呢?

因为:

p.c我们使用的是C语言的编译器gcc进行编译的,其中的函数print编译之后,在符号表中的名字为 _print

而我们链接的时候采用的是g++进行链接,也就是C++链接方式,程序在运行到调用print函数的代码时,会在符号表中寻找_print_int_int(是按照C++的链接方法来寻找的,所以是找_print_int_int而不是找_print)的名字,发现找不到,所以会t提示“未定义的引用”

此时如果我们在对print的声明中加入 extern “C” ,这个时候,g++编译器就会按照C语言的链接方式进行寻找,也就是在符号表中寻找_print,这个时候是可以找到的,是不会报错的。比如我们修改p.h为:

extern "C" void print(int a,int b);

这是结果为:

所以extern “C” 用到函数声明之前,它的作用就是告诉编译器,对于该函数的链接要采用C语言编译器的链接方式,也就是告诉编译器找_fun,而不是_fun_int_int。

如果有多个函数声明都需要在前面加extern “C”,那可以用extern “C”{}的形式。

如果你觉得对你有用,请赞一个吧

C和C++混合编程之 extern “C”的使用的更多相关文章

  1. C、C++混合编程之extern "C"

    为何要“混合编程”?举个例子: CHeader.h #ifndef C_HEADER_H #define C_HEADER_H void func(); #endif CHeader.c #inclu ...

  2. C++混合编程之idlcpp教程Python篇(9)

    上一篇在这 C++混合编程之idlcpp教程Python篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程PythonTutorial7中除了四个文件PythonTu ...

  3. C++混合编程之idlcpp教程Lua篇(9)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程LuaTutorial7中除了四个文件LuaTutorial7.c ...

  4. C++混合编程之idlcpp教程Python篇(8)

    上一篇在这 C++混合编程之idlcpp教程Python篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial6中,同样加入了四个文件:Pyt ...

  5. C++混合编程之idlcpp教程Lua篇(8)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程LuaTutorial6中,同样加入了四个文件:LuaTutori ...

  6. C++混合编程之idlcpp教程Python篇(7)

    上一篇在这 C++混合编程之idlcpp教程Python篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与PythonTutorial4工程相似,工程PythonTutorial5中,同 ...

  7. C++混合编程之idlcpp教程Lua篇(7)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件: ...

  8. C++混合编程之idlcpp教程Python篇(6)

    上一篇在这 C++混合编程之idlcpp教程Python篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程PythonTutorial4中加入了四个文件:PythonTutorial4 ...

  9. C++混合编程之idlcpp教程Lua篇(6)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程LuaTutorial4中加入了四个文件:LuaTutorial4.cpp, Tut ...

随机推荐

  1. year:2017 month:08 day:04

    2017-08-04 JAVAse 1.final修饰符 final可以修饰类,成员方法,成员变量(static 修饰符不可以修饰类) final的初始化在对象被实例化前即可final 修饰的方法不可 ...

  2. python 一个包中的文件调用另外一个包文件 实例

    python不同文件夹中模块的引用调用顺序,被调用的模块中①有类的 模块.类().方法()   ②无类的:模块.方法() test包中testIm.py 调用 test1包中testIm1.py中的方 ...

  3. python-桶排序

    桶排序 通排序非常浪费空间, 比如需要排序的范围在0~2000之间, 需要排序的数是[3,9,4,2000], 同样需要2001个空间 注意: 通排序不能排序小数 以下为从小到大代码实现 #!/usr ...

  4. JavaScript预处理

    在预处理阶段js引擎会扫描代码中用var定义的变量和用声明的方式定义的函数 用声明方式定义函数 function a(){ alert('hello world'); } 用函数表达式定义函数 var ...

  5. 木棍分割[HAOI2008]

    题目描述 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且 ...

  6. 如何使用Androidstudio创建一个新项目

    首先打开AS,然后 选择第一个选项Start a new Android Studio project 填写包名和项目名,点击next 选择项目类型,点击next 选择UI类型(都是死丢丢帮你生成的) ...

  7. 自定义Git之配置别名

    有没有经常敲错命令?比如git status?status这个单词真心不好记. 如果敲git st就表示git status那就简单多了,当然这种偷懒的办法我们是极力赞成的. 我们只需要敲一行命令,告 ...

  8. AKOJ -- 1529 -- 寻找最大数

    1529: 寻找最大数 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 107  Solved: 53 上一题SubmitStatus标签打分编辑题目信 ...

  9. 专治不会看源码的毛病--spring源码解析AOP篇

    昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些.原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们,不 ...

  10. Oracle安装oraInventory问题

    Oracle安装oraInventory问题-----------------------------2013/10/15 在使用安装Oracle软件或者使用dbca创建数据库时,所有的日志都会放在o ...