首页 > 编程语言 >实现C++和C的混合编程

实现C++和C的混合编程

时间:2023-02-15 01:34:04浏览次数:47  
标签:函数 myfun 代码 编程 C++ 混合 extern display

实现C++和C的混合编程

在 C++ 出现之前,很多实用的功能都是用 C 语言开发的,很多底层的库也是用 C 语言编写的。这意味着,如果能在 C++ 代码中兼容 C 语言代码,无疑能极大地提高 C++ 程序员的开发效率。

而恰恰答案也正是我们想要的,C++ 和 C 可以进行混合编程。但需要注意的是,由于 C++ 和 C 在程序的编译、链接等方面都存在一定的差异,而这些差异往往会导致程序运行失败。



举个例子,如下就是一个用 C++ 和 C 混合编程实现的实例项目:

//myfun.h
void display();
//myfun.c
#include <stdio.h>
#include "myfun.h"
void display(){
   printf("C++:http://c.biancheng/net/cplus/");
}
//main.cpp
#include <iostream>
#include "myfun.h"
using namespace std;
int main(){
   display();
   return 0;
}

在此项目中,主程序是用 C++ 编写的,而 display() 函数的定义是用 C 语言编写的。从表面上看,这个项目很完整,我们可以尝试运行它:

In function `main': undefined reference to `display()'

如上是调用 GCC 编译器运行此项目时给出的错误信息,指的是编译器无法找到 main.cpp 文件中 display() 函数的实现代码。导致此错误的原因,就是因为 C++ 和 C 编译程序的方式存在差异。


通过学习《C++函数重载》一节我们知道,之所以 C++ 支持函数的重载,是因为 C++ 会在程序的编译阶段对函数的函数名进行“再次重命名”,例如:

  • void Swap(int a, int b) 会被重命名为_Swap_int_int;

  • void Swap(float x, float y) 会被重命名为_Swap_float_float。


显然通过重命名,可以有效避免编译器在程序链接阶段无法找到对应的函数。


但是,C 语言是不支持函数重载的,它不会在编译阶段对函数的名称做较大的改动。仍以 void Swap(int a, int b) 和 void Swap(float x, float y) 为例,若以 C 语言的标准对它们进行编译,两个函数的函数名将都是_Swap。


不同的编译器有不同的重命名方式,但根据 C++ 标准编译后的函数名几乎都由原有函数名和各个参数的数据类型构成,而根据 C 语言标准编译后的函数名则仅有原函数名构成。这里仅仅举例说明,实际情况可能并非如此。


这也就意味着,使用 C 和 C++ 进行混合编程时,考虑到对函数名的处理方式不同,势必会造成编译器在程序链接阶段无法找到函数具体的实现,导致链接失败。

幸运的是,C++ 给出了相应的解决方案,即借助 extern "C",就可以轻松解决 C++ 和 C 在处理代码方式上的差异性。



extern "C"

extern 是 C 和 C++ 的一个关键字,但对于 extern "C",读者大可以将其看做一个整体,和 extern 毫无关系。


extern "C" 既可以修饰一句 C++ 代码,也可以修饰一段 C++ 代码,它的功能是让编译器以处理 C 语言代码的方式来处理修饰的 C++ 代码。


仍以本节前面的实例项目来说,main.cpp 和 myfun.c 文件中都包含 myfun.h 头文件,当程序进行预处理操作时,myfun.h 头文件中的内容会被分别复制到这 2 个源文件中。对于 main.cpp 文件中包含的 display() 函数来说,编译器会以 C++ 代码的编译方式来处理它;而对于 myfun.c 文件中的 display() 函数来说,编译器会以 C 语言代码的编译方式来处理它。


为了避免 display() 函数以不同的编译方式处理,我们应该使其在 main.cpp 文件中仍以 C 语言代码的方式处理,这样就可以解决函数名不一致的问题。因此,可以像如下这样来修改 myfun.h:

#ifdef __cplusplus
extern "C" void display();
#else
void display();
#endif

可以看到,当 myfun.h 被引入到 C++ 程序中时,会选择带有 extern "C" 修饰的 display() 函数;反之如果 myfun.h 被引入到 C 语言程序中,则会选择不带 extern "C" 修饰的 display() 函数。由此,无论 display() 函数位于 C++ 程序还是 C 语言程序,都保证了 display() 函数可以按照 C 语言的标准来处理。

再次运行该项目,会发现之前的问题消失了,可以正常运行:

C++:http://c.biancheng/net/cplus/

在实际开发中,对于解决 C++ 和 C 混合编程的问题,通常在头文件中使用如下格式:

#ifdef __cplusplus
extern "C" {
#endif
void display();
#ifdef __cplusplus
}
#endif

由此可以看出,extern "C" 大致有 2 种用法,当仅修饰一句 C++ 代码时,直接将其添加到该函数代码的开头即可;如果用于修饰一段 C++ 代码,只需为 extern "C" 添加一对大括号{},并将要修饰的代码囊括到括号内即可。

标签:函数,myfun,代码,编程,C++,混合,extern,display
From: https://www.cnblogs.com/dzdiy/p/17121360.html

相关文章

  • C/C++程序设计课程设计[2023-02-15]
    C/C++程序设计课程设计[2023-02-15]程序设计课程设计要求1、课程设计分组合作完成,每个小组最多3人。2、每组成员(不得超过3人)分工合作完成一个课程设计题目,每个人的任......
  • 第5章 函数式编程**-函数和方法,高阶函数,匿名函数,函数柯里化,闭包,递归,控制抽象(传值参数,
    第5章函数式编程-函数和方法,高阶函数,匿名函数,函数柯里化,闭包,递归,控制抽象(传值参数,传名参数),惰性加载目录第5章函数式编程-函数和方法,高阶函数,匿名函数,函数柯里化,闭包......
  • C++类的组合
    title:C++类的组合案例date:2022-05-1819:07:35tags:C++category:cpp参考书籍:C++PrimerEssentialC++编译器:gcc/g++C++类的组合什么是类的组合类的组合就是以......
  • 高效字符串匹配算法——BM 算法详解(C++)
    定义BM算法是由Boyer和Moore两人提出的一种高效的字符串匹配算法,被认为是一种亚线性算法(即平均的时间复杂度低于线性级别),其时间效率在一般情况下甚至比KMP还要快3......
  • 转换率优化教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介转换率优化定义-从定义,基础知识,了解客户,目标设置,误区,优化计划,用户体验和漏斗优化,目标网页优化,降低退回和退出率,测试和优化,测量结果,学习转换率优化优化技巧,结论。......
  • javascript 高级编程系列 - Web Workers
    Webworkders的规范让javascript在后台运行脱离了UI线程,从而解决了大量计算阻塞UI线程导致卡死的问题。在Webworkers没有出现之前,我们可以使用window.setTimeout异步方......
  • 场景编程集锦 - 二次元美女学Python
    第1章场景描述白小灵,人如其名,身型娇小,有点古灵精怪,大学动漫专业毕业,是典型的二次元美女。在大四那一年,她遇上了阳光帅气、家境殷实的白马王子小帅,她认定小帅就是自己的菜,随......
  • 各个编程语言的优缺点,你适合哪种?
    TIOBE编程语言排行前10中,各个编程语言的优缺点如下:Python:优点:易学易用,具有大量的第三方库和工具支持,适用于数据分析、人工智能等领域。缺点:运行速度相对较慢,不适用......
  • c++通过http协议校时
    由于IP黑白名单的限制,我们能访问的ip和域名资源非常有限,现将通过http协议授时方法整理如下: #include<cstdio>#include<string.h>#include<curl/curl.h>#inclu......
  • 编程基础与python介绍
    1、计算机内部存储数据的原理2、编程语言的发展史3、python解释器版本4、多版本的共存(重要)5、python的运行方式6、python的下载与安装7、路径8.环境变量 ......