当前位置: 首页 > news >正文

C++~从编译链接的过程看为什么C++支持重载?externC有什么用?

C++为什么支持重载?externC有什么用?从编译链接的过程中就可以找到答案,首先聊一聊编译链接的过程

总共分为四个过程——预处理,编译,汇编和链接。

1.预处理--它做的主要是头文件展开、宏替换、条件编译、去掉注释等工作。预处理结束后,会生成预编译文件(.i)

2.编译--这个阶段会检查语法,将经过预处理后的预编译文件转换成特定汇编代码,生成汇编文件(.s)

3.汇编--将编译阶段生成的汇编文件转化成机器码,生成可重定位目标文件(.o/.obj)。

4.链接--将多个目标文件连接成最终可执行目标文件(.out/.exe)。有些文件里面调用的函数只有声明,函数的定义是在另一个文件中定义的,这个时候就需要通过这个过程根据函数的地址将其链接起来。


那么C++为什么支持重载呢?

        编译的过程中会生成一个符号表将对应的函数名和函数的地址映射起来,这样在链接的时候就可以根据函数名找到对应函数的地址并将其链接起来。

        在c++中,函数名在编译后会根据相应的函数名修饰规则修饰,即使函数名相同,只要函数的参数数量,参数类型,参数顺序不一样,修饰后的函数名就不一样,这样链接的时候也可以根据修饰后的函数名找到对应的函数地址进行链接。

        但是在c语言中,编译后的函数名就是原来的函数名,所以如果函数名相同,编译就会报错。


externC有什么用?

在我们调用库的时候,c++可以调用c++的库,c可以调用c的库

实际上,c++中也可以调用c的静态库和动态库,c中也可以调用c++的静态库和动态库

        由于C和C++编译器对函数名字修饰规则不同,可能就会导致链接失败,因为链接的时候会根据符号表中的函数名和对应的地址,将其链接起来,c++在编译的时候对函数名的修饰规则是不一样的,就算是同样的函数名,参数类型不同,函数的修饰名也会不同,c语言是直接原模原样复制下来的。两者对函数名的修饰方式不同。

        在该种场景下,就需要使用extern "C"。在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。

        如果是c调用c++的库,那就在c++库中加上extern C,按照C的函数修饰规则去编译,但是不能这样子直接加,这样c++库这边可以编译通过,但是当这些函数在头文件里面展开的时候就会出错,因为展开后再c的环境中,c语言不认识externc,这是c++的语法。

        这个时候可以使用条件编译+宏的方式来解决,如图所示。这样在c++库这边有加externC,编译的时候函数是按照C语言规则来编译的。当里面的内容展开到c的文件里面的时候,条件编译会将externC去掉,所以c语言编译也能够通过,这样就可以成功调用了。

相关文章:

  • App移动端测试【10】Monkey自定义脚本案例
  • springboot 整合dubbo3开发rest应用
  • 【机器学习】集成学习:使用scikitLearn中的BaggingClassifier实现bagging和pasting策略
  • 算法与数据结构 --- 串,数组和广义表 --- 串
  • 【Python Web】Flask框架(四)Bootstrap的使用及案例
  • MySQL------数据表的创建和简单、条件,模糊查询
  • 【arduino】I/O端口操作
  • 微服务项目:尚融宝(44)(核心业务流程:借款申请(1))
  • 11、Java——吃货联盟订餐系统(对象+数组)
  • Java高性能实体类转换工具MapStruct
  • C++引用的概念
  • 基于ResNetRS的宝可梦图像识别
  • SpringBoot+Easyexcel读取多sheet支持xls,xlsx版本的excel
  • Ubuntu22.04 安装配置流水账
  • SwiftUI 动态岛开发教程之什么是Dynamic Island,快速完整demo
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • android 一些 utils
  • CSS盒模型深入
  • JS数组方法汇总
  • Python学习笔记 字符串拼接
  • react 代码优化(一) ——事件处理
  • SQLServer插入数据
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • Vue 动态创建 component
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 深度学习在携程攻略社区的应用
  • 写给高年级小学生看的《Bash 指南》
  • 一道闭包题引发的思考
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 正则与JS中的正则
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • ​linux启动进程的方式
  • #1015 : KMP算法
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (4)logging(日志模块)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (第27天)Oracle 数据泵转换分区表
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (四)图像的%2线性拉伸
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (原創) 未来三学期想要修的课 (日記)
  • (转)nsfocus-绿盟科技笔试题目
  • ***通过什么方式***网吧
  • *上位机的定义
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET Core Web APi类库如何内嵌运行?
  • .Net Core与存储过程(一)
  • .net wcf memory gates checking failed
  • .NET 跨平台图形库 SkiaSharp 基础应用