C/C++源文件到可执行文件、C++能重载C语言不能重载本质

C/C++源文件到可执行文件

翻译环境

C/C++源文件到可执行文件、C++能重载C语言不能重载本质_第1张图片


C/C++源文件到可执行文件、C++能重载C语言不能重载本质_第2张图片


过程总结:

■ 1、组成一个程序的每个源文件通过编译过程分别转换为对应的每个目标文件。

■ 2、每个目标文件通过链接器捆绑在一起,形成单一而完整的可执行程序。

■ 3、链接器同时也会引入标准C/C++库函数中任何被该程序所用到的函数,而且还会搜索程序员个人的程序库,将其需要的函数也链接到程序中来。

翻译环境中的每一步具体干了什么

每个过程总结:

1. 预处理:为正式编译做准备。1.头文件展开。2.宏替换。3.去掉注释。在Linux环境下用命令gcc -E test.c -o test.i 预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。

2. 翻译:把C/C++语言代码翻译成汇编代码。1.语法分析,语义分析,词法分析。2.符号汇总。等在Linux环境下用命令gcc -E test.c -o test.i 预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。

3. 汇编:把汇编代码转换成二进制代码。形成符号表。等在Linux环境下用命令gcc -S test.c编译完成之后就停下来,结果保存在test.s中。

4. 链接:生成可执行代码。合并段表,符号表的合并和重定位。等在Linux环境下用命令gcc test -o test.out(名字可随意取)。

C++能重载C语言不能重载本质

函数重载定义:是函数的一种特殊情况,C++允许在同一个作用域中声明几个功能类似的同名函数。这些同名函数的形参列表(参数个数或类型或顺序不同),常用来处理实现功能类似数据类型不同的问题。

int add(int left,int right){
     
	return left+right;
}
double add(double left,double right){
     
	return left+right;
}
long add(long left,long right){
     
	return left+right;
}

名字修饰

问题:为什么C++支持函数重载,而C语言中不支持函数重载?

在上面我们已经知道了一个程序要生成可执行程序要经历: 预处理、编译、汇编、链接 四个阶段。

1.例如:当前a.cpp中调用了b.cpp中定义的Add函数时。编译后链接前, a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?

2.链接阶段:就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。

3.那么链接时,面对Add函数,连接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

4.由于Windows下vs的修饰规则过于复杂,而Linux下gcc的修饰规则简单易懂,下面我们使用了gcc演示了这个修饰后的名字。

#include

int add(int x,int y){
     
  return x+y;
}

int main(){
     
 	printf("%d\n",add(1,5));
 	return 0;
}       

C/C++源文件到可执行文件、C++能重载C语言不能重载本质_第3张图片

#include

int add(int x,int y){
     
	return x+y;
}
double add(double x,double y){
     
	return x+y;
}
int main(){
     
	cout<<add(1,5);
	return 0;
}

C/C++源文件到可执行文件、C++能重载C语言不能重载本质_第4张图片

通过实列我们可以看出对于C语言的函数修饰后名字不变。而C++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。这个就是为什么重载函数要求参数列表的个数、类型或者顺序不一样了,因为编译后要保证生成的名字修饰不同。

extern “c”

有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译。

extern "C" int Add(int left, int right);//告诉编译器将该函数使用C语言规则来编译。

int main()
{
     
	Add(1,2);
	return 0;
}

你可能感兴趣的:(C/C++,c++)