打印
[信息]

为什么C语言不能函数重载

[复制链接]
509|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
flycamelaaa|  楼主 | 2023-8-17 15:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前言
在日常的开发中,我们有时会遇到根据不同情景,想通过传入不同类型的参数,而调用统一的函数接口,即函数重载。 在C++中原生支持了函数重载, 而在C语言中并不支持,只能通过一些技巧来变相解决, 如定义flag形参, 根据flag值不同,进行不同的处理。例如:
  • void test(void *a, void *b, int flag)
  • {
  •                         if(flag == 1)
  •       {
  •                                                 int *m_a = (int *)a;
  •             int *m_b = (int *)b;
  •       }
  •                   else if(flag == 2)
  •       {
  •                               char *m_a = (char *)a;
  •             char *m_b = (char *)b;
  •       }
  •            else if(flag == 3)
  •      {
  •                               int *m_a = (int *)a;
  •            char *m_b = (char *)b;
  •      }
  • }


而在C++中,直接函数重载:
  • //===============函数重载===================
  • void test(int *a, int *b)
  • {
  •                         //函数一
  • }
  • void test(int *a, char *b)
  • {
  •                         //函数二
  • }
  • void test(char *a, double *b)
  • {
  •                         //函数三
  • }
  • //===============测试======================
  • int main(void)
  • {
  •       //调用函数一
  •       int a, b;
  •       test(&a, &b);
  •                         //调用函数二
  •                         int c;
  •                         char d;
  •                         test(&c, &d);
  •                         //调用函数三
  •                         char e;
  •                         double f;
  •                         test(&e, &f);
  •                         return 0;
  • }


注意: 函数返回值不是函数重载的判断标准!
使用objdump工具反汇编
大家都知道了在C语言中不能函数重载, 究其原因是否思考过呢?接下来我们以下c和c++代码为例子,分别用gcc和 g++编译, 然后再用objdump工具反汇编看看得到的汇编代码有什么区别。
C语言代码:
使用编译无警告无错误, 使用以下命令:
objdump -d c_test > c_res


使用vi(vim)打开反汇编结果c_res文件:


从上图可知,在C语言中,函数经过C编译器编译后,最终得到的符号表(对应函数地址)只包含函数名,跟函数返回类型, 参数类型都无关系。
接下来,我们在看看C++代码:


使用g++(c++编译器)编译后,同样再用objdump工具反汇编:


得到反汇编结果文件cpp_res,vi打开:


从上图我们可以看到,函数和编译后符号对应关系:
函数一:void test(int *a, int *b) —— _Z4testPiS_
函数二:char test(char *a, int *b) —— _Z4testPcPi
函数三: int test(char *a, double *b) —— _Z4testPcPd
分析:因为函数一, 二,三,3个函数返回值类型都不同,而最终得到的符号前缀都是“_Z4”,因此验证了函数返回值类型不是函数重载的判断依据。中间的"test"是函数名,这个容易理解,而剩余的3个后缀:
PiS_ 对应 函数一的参数类型 (int , int) 的首字母i, 这里因为2个类型一致,编译处理下
PcPi 对应 函数二的参数类型(char, int)的首字母ci
PcPd 对应 函数三的参数类型(char , double)的首字母cd
因此函数参数类型是函数重载的判断依据!
小结
根据上面的objdump工具反汇编查看汇编代码中符号,我们知道了在C语言中,C编译器在函数符号处理时,只以函数名称为符号,因此无法进行函数重载,同时我们也明白了C++中能够使用函数重载,只是编译器进行了处理,最终实际调用的还是不同的函数,但统一了接口。
最后再次强调下, 要想学好编程语言,尤其是编译语言,要站在编译器的角度思考问题,我们可以通过像objdump等工具来辅助我们反推理解。

使用特权

评论回复
评论
xch 2023-8-18 13:19 回复TA
还是不知道为什么? 
zlf1208 2023-8-18 10:16 回复TA
知其然,更要知其所以然 
沙发
Jacquetry| | 2023-8-17 23:00 | 只看该作者
也可以直接用c++写啊。现在不是都支持c++了嘛

使用特权

评论回复
评论
zlf1208 2023-8-18 10:21 回复TA
你说的楼主自然是知道的,但是楼主说的你却不明白,思路有本质的不同 
板凳
sfd123| | 2023-8-19 09:10 | 只看该作者
楼主是高手!而且是愿意知其然,并且知其所以然的  技术大牛!向你学习!

使用特权

评论回复
地板
童雨竹| | 2024-3-1 07:26 | 只看该作者

给瞬间电流提供低阻抗导通路径

使用特权

评论回复
5
Wordsworth| | 2024-3-1 08:29 | 只看该作者

最典型的应用就是放大电路中的高低音频控制

使用特权

评论回复
6
Clyde011| | 2024-3-1 09:32 | 只看该作者

器件整合的再紧凑都无法发挥最大的效率

使用特权

评论回复
7
公羊子丹| | 2024-3-1 10:25 | 只看该作者

需要设置电压钳位电路予以保护D3、N3构成的回路

使用特权

评论回复
8
万图| | 2024-3-1 11:28 | 只看该作者

需要串联一个限流电阻在其中

使用特权

评论回复
9
Uriah| | 2024-3-1 12:31 | 只看该作者

当人接触任何东西时,体内的电荷就会放电。

使用特权

评论回复
10
帛灿灿| | 2024-3-1 14:27 | 只看该作者

有不普通的门道

使用特权

评论回复
11
Bblythe| | 2024-3-1 15:30 | 只看该作者

只能处理较小的能量

使用特权

评论回复
12
周半梅| | 2024-3-1 17:26 | 只看该作者

电路正常工作

使用特权

评论回复
13
Pulitzer| | 2024-3-1 18:29 | 只看该作者

灌封前基材外观保持清洁和干燥。将混合好的胶料灌注于需灌封的器件内

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

658

主题

2751

帖子

0

粉丝