当前位置:网站首页>编译预处理等细节
编译预处理等细节
2022-08-05 01:56:00 【一般路过半缘君】
敲过代码的人都知道,任何一个程序都需要经过编译和链接才能生成可执行程序,才能使代码运行起来,那么编译和链接的过程中,编译器做了哪些事,使得程序可以执行呢?
程序的翻译环境和执行环境
国际c标准中规定,任何一种实现,都存在两个不同的环境。
1:翻译环境:将代码翻译成机器指令;
2:执行环境:用来实际执行代码;
而我们重点需要了解的是翻译环境究竟干了什么,生成了可执行的程序。
翻译环境
图1.编译文件
如图1.编译文件所示,每一个源文件都会经过编译器生成对应的目标文件,然后经过链接器在链接库中查找对应的头文件,最后生成可执行文件,这里的源文件可以不止一个.c文件,可能有多个.c文件。
实际操作上我们可以看到,文件编译运行后,会生成对应的.exe文件,如下:
我们可以看到,当我们没有编译运行的时候,项目文件夹中只有.c源文件,而当我们编译运行后,就能发现文件夹中多了一个Debug文件夹,里面有编译文件的.exe文件;
图2
图3
图4
每一个源文件在编译过程中都会经过编译器生成对应的目标文件,如图三中的test.c就生成了对应的test.obj文件,而每个目标文件(同一个项目中的)都会经过链接器捆绑在一起形成单一而完整的可执行程序,正如图4的test_8_3.exe(项目生成的可执行程序),连接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
当然这只是笼统的讲法,实际上编译和链接可以分为四步。
图5.编译链接具体操作
将编译与链接拆开后,实际上分为以上四个步骤,而每一个步骤都会生成不同的文件;
但是VS是集成开发环境,不好观察细节,于是我们只能在Linux上观察细节。
比如我们在Linux上写上如下代码:
预处理细节
当我们想观察预处理后会发生什么事,我们应该这样输入
图6 test.i
而出现的这些代码实际上就是头文件stdio.h中所有的函数。
当然,预处理并不只是只是这样,它还会将所有注释删除,并且将#define符号转换成对应的内容。就比如我#define MAX 10000;那么当我在define下面使用MAX的时候,所有MAX会被替换成10000,当我#define sum 3+2;那么下面使用sum的时候,所有sum被被替换成3+2;然后编译器会将#define那一行给删除掉(因为已经替换完成了)。
编译细节
想看到编译细节我们应该输入gcc -S test.c
这样编译器会生成一个名为test.s的文件。
打开test.s文件我们可以发现,里面全部是汇编代码,在编译阶段,编译器会进行语法分析,词法分析,语义分析,符号汇总等操作,其中最重要的是符号汇总。
符号汇总
符号汇总会将全局变量,定义的函数(包括main函数) 进行汇总;
接下来就进行汇编阶段;
汇编细节
之后再输入gcc -c test.c
生成了test.o文件
这个文件是二进制存储的,内部东西都是二进制的东西;
于是我们便明白了汇编会将汇编代码转换为二进制代码
如图7
图7
汇编中有一个操作是形成符号表;
这个其实和编译中的符号汇总是相关联的,我们test.c经过编译生成对应的test.s文件后,编译器会将对应的符号汇总,然后在汇编环节,生成一个符号表,在这个环节,编译器会给符号表中的每一个符号一个地址,用来访问,就比如这里的test.c文件经过汇编后,会给Add,g_val,main三个符号一个地址,当然,如果Add函数或者g_val变量是从外部文件声明的话,符号表会将给它们一个无效地址,之后在链接阶段使用符号表。
链接细节
当所有源文件按照elf格式生成了对应的.o文件后,编译器会给每一个.o文件按照elf格式生成一个段表,段表每一个空位存储对应的地址,然后在链接阶段会进行段表合并,它会将相同名称的符号合并,取符号表中的有效地址放在对应的符号表中,这个符号表就是决定之后可执行程序能否使用这个函数,若是符号表中存的是无效地址,就无法使用该函数,导致链接错误。
若是在这一系列操作没有发生错误,就成功生成了一个可执行程序。
边栏推荐
- 亚马逊云科技 + 英特尔 + 中科创达为行业客户构建 AIoT 平台
- 迁移学习——Joint Geometrical and Statistical Alignment for Visual Domain Adaptation
- 如何发现一个有价值的 GameFi?
- 蓝牙Mesh系统开发四 ble mesh网关节点管理
- Exercise: Selecting a Structure (1)
- 关于#sql shell#的问题,如何解决?
- Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛?
- 接口自动化测试框架postman tests常用方法
- 【机器学习】21天挑战赛学习笔记(二)
- 测试工作这么难找吗?今年32,失业2个月,大龄测试工程师接下来该拿什么养家?
猜你喜欢
【MySQL series】- Does LIKE query start with % will make the index invalid?
hypervisor相关的知识点
基于OpenVINO工具套件简单实现YOLOv7预训练模型的部署
软件测试技术之最有效的七大性能测试技术
10年测试经验,在35岁的生理年龄面前,一文不值
Jincang database KingbaseES V8 GIS data migration solution (3. Data migration based on ArcGIS platform to KES)
iNFTnews | 对体育行业和球迷来说,NFT可以带来什么?
[Word] #() error occurs after Word formula is exported to PDF
如何逐步执行数据风险评估
LPQ (local phase quantization) study notes
随机推荐
Live preview | 30 minutes started quickly!Look at credible distributed AI chain oar architectural design
【七夕如何根据情侣倾听的音乐进行薅羊毛】背景音乐是否会影响情侣对酒的选择
张驰咨询:揭晓六西格玛管理(6 Sigma)长盛不衰的秘密
在这个超连接的世界里,你的数据安全吗
亚马逊云科技 + 英特尔 + 中科创达为行业客户构建 AIoT 平台
Oracle encapsulates restful interfaces into views
重新审视分布式系统:永远不会有完美的一致性方案……
10年测试经验,在35岁的生理年龄面前,一文不值
"Dilili, wait for the lights, wait for the lights", the prompt sound for safe production in the factory
基于OpenVINO工具套件简单实现YOLOv7预训练模型的部署
没有对象的程序员如何过七夕
HOG feature study notes
XMjs跨域问题解决
汇编语言之源程序
LPQ (local phase quantization) study notes
【TA-霜狼_may-《百人计划》】图形4.3 实时阴影介绍
CMS建站流程
跨域解决方案
Are testing jobs so hard to find?I am 32 this year and I have been unemployed for 2 months. What should an older test engineer do next to support his family?
How to create an rpm package