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

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

翻译环境

在这里插入图片描述


在这里插入图片描述


过程总结:

■ 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演示了这个修饰后的名字。注意图片中是汇编指令,我将一个源文件编译成可执行文件后转到它的汇编代码,我们来看看汇编代码中的函数的名称。命令objdump -S testc[可执行文件名]

#include<stdio.h>

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

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

在这里插入图片描述

#include<iostream>

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++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。这个就是为什么重载函数要求参数列表的个数、类型或者顺序不一样了,因为编译后要保证生成的名字修饰不同。

extern “c”

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

//例一:
extern "C" int Add(int left, int right);//告诉编译器将该函数使用C++语言规则来编译。然后链接的时候就能正常链接

int main()
{
	Add(1,2);
	return 0;
}
//例二:如果函数太多可以使用这种形式只需要声明一次,不需要每一个函数前面都加extern "C"
#ifdef __cplusplus
extern "C" {
#endif

#include<stdio.h>
int strcmp(const char *,const char *);


#ifdef __cplusplus
}
#endif
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值