龙空技术网

C语言学习篇(32)——为什么C语言不能函数重载

嵌入式笔记v 1104

前言:

目前朋友们对“c语言中的函数不能单独进行编译”都比较关注,各位老铁们都想要分析一些“c语言中的函数不能单独进行编译”的相关资讯。那么小编在网摘上网罗了一些对于“c语言中的函数不能单独进行编译””的相关资讯,希望小伙伴们能喜欢,兄弟们一起来学习一下吧!

前言

在日常的开发中,我们有时会遇到根据不同情景,想通过传入不同类型的参数,而调用统一的函数接口,即函数重载。 在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等工具来辅助我们反推理解。

标签: #c语言中的函数不能单独进行编译 #c语言编译器不能编译怎么办呢 #函数重载的原则