详解C语言为什么不支持函数重载

本文探讨了C语言不支持函数重载的原因,分析了C++如何通过不同的符号表命名规则实现重载。在C语言中,相同的函数名在符号表中会导致冲突,而C++使用-mangled-name规则区分重载函数,使得链接器能正确解析。
摘要由CSDN通过智能技术生成


在这里插入图片描述

本篇文章我们来讲解为什么C语言不支持函数重载,而C++可以支持,如果对函数重载的基本概念还不清楚,可以看一下我的上篇文章:C++入门前菜

在本文章中,我们需要搞懂两个问题:
1.C++是如何支持重载的?
2.为什么C语言不能支持?

首先,我们需要了解程序编译链接的过程(这里做大致介绍),我用一张图来大致描述编译链接的过程

编译链接过程

  • 其中,组成程序的所有源文件(也就是我们通常所说的.c.cpp文件)通过编译过程生成目标文件
  • 每个目标文件由链接器(linker)捆绑在一起,组成一个单一的可执行程序
  • 链接器在链接时也同时会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接在程序中

然后编译又可分为预编译,编译,汇编三个过程.
预编译:在预编译阶段,编译器大致会做:

  • 头文件的展开
  • 删除注释
  • 条件编译
  • 宏替换

生成test.i文件

编译:在编译阶段,编译器会

  • 将C语言代码转换成汇编代码(test.s)
  • 进行语法分析,词法分析,语义分析
  • 符号汇总

汇编:在汇编阶段,编译器会把汇编代码转换成二进制指令(test.o)形成符号表.

链接:在链接阶段,链接器会

  • 合并段表
  • 符号表的合并和重定位
  • 找调用函数的地址,链接对应上,合并到一起

最终生成可执行文件test.exe.

接下来,我们着重来看看C语言和C++在生成符号表这一过程中有什么不同?我会在Linux系统中写代码并查看编译过程为大家演示:

🚀1.C语言为什么不能支持重载?

首先,我们创建了三个文件:

然后我们通过gcc -o mytest f.c test.c来生成可执行文件mytest,接着我们再用objdump -S mytest命令就可以跳转来查看此程序生成的符号表.如图:

在这里插入图片描述
在图中,可以看见,当C语言在编译过程生成符号表时,它的函数在符号表中的名字就只是用自定义的函数名来表示,所以,如果在C语言中写了函数重载,那么它会在符号表中生成两个名字一模一样的函数名,那这样,在链接的过程中它的符号表中会有两个完全一样的函数名,那编译器怎么知道要去找哪个呢?

所以,这个时候就发生了错误.这也就是C语言不能支持重载的原因.

🪐2.C++为什么能够支持重载?

同样的,我们也来观察C++在编译过程中产生的符号表:

首先我们定义三个文件:f.cppf.htest.cpp

然后我们通过objdump -S mytest命令来查看符号表:
在这里插入图片描述
我们可以看到,在C++中,生成符号表时给函数的取名规则是-Z 函数名长度 函数名 参数类型首字母,这样不同于C语言的取名方式,也就将发生函数重载的函数区别开来,这样,在链接过程中,编译器也就知道在符号表寻找函数时也就知道该去寻找哪一个对应的函数.

这也就是C语言为什么不能支持函数重载而C++却可以.

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉默.@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值