当前位置:网站首页>编译预处理等细节
编译预处理等细节
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格式生成一个段表,段表每一个空位存储对应的地址,然后在链接阶段会进行段表合并,它会将相同名称的符号合并,取符号表中的有效地址放在对应的符号表中,这个符号表就是决定之后可执行程序能否使用这个函数,若是符号表中存的是无效地址,就无法使用该函数,导致链接错误。
若是在这一系列操作没有发生错误,就成功生成了一个可执行程序。
边栏推荐
- Log an error encountered when compiling google gn "I could not find a ".gn" file ..."
- 习题:选择结构(一)
- Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛?
- 10年测试经验,在35岁的生理年龄面前,一文不值
- 从一次数据库误操作开始了解MySQL日志【bin log、redo log、undo log】
- HOG feature study notes
- 如何逐步执行数据风险评估
- Fragment visibility judgment
- ".NET IoT from scratch" series
- Greenplum Database Fault Analysis - Can a Soft Connection Be Made to the Database Base Folder?
猜你喜欢

如何发现一个有价值的 GameFi?

Transfer Learning - Distant Domain Transfer Learning

Day Fourteen & Postman

"Dilili, wait for the lights, wait for the lights", the prompt sound for safe production in the factory

硬实力和软实力,哪个对测试人来说更重要?

LPQ (local phase quantization) study notes

.Net C# Console Create a window using Win32 API

行业现状?互联网公司为什么宁愿花20k招人,也不愿涨薪留住老员工~

iNFTnews | 对体育行业和球迷来说,NFT可以带来什么?

10年测试经验,在35岁的生理年龄面前,一文不值
随机推荐
Fragment visibility judgment
1349. Maximum number of students taking the exam Status Compression
迅睿cms网站搬迁换了服务器后网站不能正常显示
Xunrui cms website cannot be displayed normally after relocation and server change
pytorch的使用:卷积神经网络模块
张驰咨询:揭晓六西格玛管理(6 Sigma)长盛不衰的秘密
没有对象的程序员如何过七夕
亚马逊云科技携手中科创达为行业客户构建AIoT平台
PHP技能评测
oracle将restful接口封装到视图中
Exercise: Selecting a Structure (1)
Exploding the circle of friends, Alibaba produced billion-level concurrent design quick notes are too fragrant
新来个技术总监,把DDD落地的那叫一个高级,服气
[Unity Entry Plan] Handling of Occlusion Problems in 2D Games & Pseudo Perspective
原生js实现多选框全部选中和取消效果
ExcelPatternTool: Excel表格-数据库互导工具
《.NET物联网从零开始》系列
LPQ (local phase quantization) study notes
<开发>实用工具
HOG特征学习笔记