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

为什么C++支持函数重载而C语言不支持?

为什么C++支持函数重载而C语言不支持?

主要代码

先看工程中的三段代码

//文件名 f.h

#include <stdio.h>

int Add(int a,int b);
double Add(double a, double b);
//文件名 f.c

#include "f.h"

int Add(int a,int b){
	return a + b;
}

double Add(double a, double b){
	return a + b;
}
//文件名 test.c

#include "f.h"

int main(){

	int a = Add(1,2);
	double b = Add(1.1,2.2);
	printf("%d,%f\n",a,b);

	return 0;
}

运行结果

C语言编译:
在这里插入图片描述

C++编译结果:

上述代码是对函数重载的简单运用,但在C语言编译下和C++语言编译下结果不同,因为C++语言支持函数重载,而C语言不支持,但为什么C语言不支持函数重载呢?

程序编译过程

在C/C++中一个程序运行起来需要经历几个过程:

阶段文件:f.h f.c test.c

1、预处理 -> 头文件展开、宏替换、条件编译、去掉注释

f.i test.i

2、编译 -> 检查语法,生成汇编代码

f.s test.s

3、汇编 -> 把汇编代码转换成二进制代码

f.o test.o

4、链接 -> 把几个二进制代码文件整合成一个可执行文件

a.out(linux系统中)

在链接的过程中并不是代码的简单合并而是需要关注被调用函数的地址,先来看C环境下main函数的汇编代码(为了程序能成功编译,将int Add 改为int Addi:
在这里插入图片描述

在40057f和4005ad处是对int Addi(int a,int b),double Add(double a,double b)的调用

call + 函数地址是汇编语言对于函数调用的语法,但上述汇编代码是在程序连接完成后生成的,在第二节程序编译过程中的汇编阶段就需要生成汇编代码。在这个过程中test.s 中关于函数调用的汇编代码临时写为 call ? Addi ,中间的?是Addi函数的地址,在这个过程中还不能确定,只有在链接的过程中才能确定,在链接的时候是如何确定函数地址的呢?

这是因为在编译过程中会为每个文件生成一个符号表,用于存放函数地址,例如f.c文件在C语言中的符号表可以表示为:

函数名函数地址
Add400541
Addi40052d

在链接的过程中C语言编译器就会根据函数名去寻找函数地址,但是如果有重名函数,编译器就会无法根据函数名去寻找函数地址,因为符号表里有两个Add,无法确定哪个才是需要的函数地址。

那么C++是如何实现函数重载的呢?
我们来对比一下C 和C++编译出的汇编代码

C++汇编代码:
在这里插入图片描述
我们会发现在函数调用语句中C++使用的函数名是 _Z3Addii 和_Z3Adddd

4005af: e8 a9 ff ff ff callq 40055d <_Z3Addii>

4005dd: e8 8f ff ff ff callq 400571 <_Z3Adddd>

原来 C++使用了独特的函数名修饰规则,使得同名函数的重载,在符号表里会有不同的函数名,

修饰规则(以_Z3Addii为例):
_是固定前缀,Z为linux系统固有前缀,3为函数名符号长度,Add为函数名,长度为3,最后的ii为函数参数的类型。

C++编译下f.c文件的符号表:

函数名函数地址
_Z3Addii40055d
_Z3Adddd400571

这样函数在编译的过程中对于同名函数的不同重载就会有不同的函数修饰名,就不会链接出错。


http://www.kler.cn/a/458828.html

相关文章:

  • 【Ubuntu使用技巧】Ubuntu22.04无人值守Crontab工具实战详解
  • playwright的page.wait_for 常见用法
  • Docker部署ubuntu测试环境
  • webpack打包node后端项目
  • C#:多线程 简单示例
  • debian系linux安装mysql
  • “技术学习”(Technical Learning)在英文中的多种表达方式
  • 第十六届蓝桥杯模拟赛(第一期)(C语言)
  • HarmonyOS NEXT 实战之元服务:静态案例效果---本地生活服务
  • SkyWalking Agent 配置 Spring Cloud Gateway 插件解决日志错误
  • Momentum Contrast for Unsupervised Visual Representation Learning论文笔记
  • Django多字段认证的实现
  • python脚本加载ui页面:PySide6设计的页面
  • SQL 实战:窗口函数进阶 – 实现复杂滑动窗口与动态累计计算
  • 大数据与机器学习(它们有何关系?)
  • Mac电脑python多版本环境安装与切换
  • Selenium之Web元素定位
  • Android笔试面试题AI答之Android基础(7)
  • hive-sql 连续登录五天的用户
  • 【GeekBand】C++设计模式笔记18_State_状态模式
  • 【2024年-6月-21日-开源社区openEuler实践记录】探索 intel-kernel:英特尔架构内核优化之路
  • [TOTP]android kotlin实现 totp身份验证器 类似Google身份验证器
  • 环,域,体,整区,理想,极大理想,
  • 配置hive支持中文注释
  • Lombok是银弹?还是陷阱?
  • golang标准库archive/tar实现打包压缩及解压