当前位置:网站首页>编译预处理等细节
编译预处理等细节
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上写上如下代码:
预处理细节
当我们想观察预处理后会发生什么事,我们应该这样输入

而出现的这些代码实际上就是头文件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格式生成一个段表,段表每一个空位存储对应的地址,然后在链接阶段会进行段表合并,它会将相同名称的符号合并,取符号表中的有效地址放在对应的符号表中,这个符号表就是决定之后可执行程序能否使用这个函数,若是符号表中存的是无效地址,就无法使用该函数,导致链接错误。
若是在这一系列操作没有发生错误,就成功生成了一个可执行程序。
边栏推荐
- Transfer Learning - Distant Domain Transfer Learning
- Domain Driven Design - MDD
- 详细全面的postman接口测试实战教程
- 刷爆朋友圈,Alibaba出品亿级并发设计速成笔记太香了
- 汇编语言之源程序
- <开发>实用工具
- 直播回放含 PPT 下载|基于 Flink & DeepRec 构建 Online Deep Learning
- 超越YOLO5-Face | YOLO-FaceV2正式开源Trick+学术点拉满
- Greenplum Database Fault Analysis - Can a Soft Connection Be Made to the Database Base Folder?
- "Dilili, wait for the lights, wait for the lights", the prompt sound for safe production in the factory
猜你喜欢
【TA-霜狼_may-《百人计划》】图形4.3 实时阴影介绍
如何逐步执行数据风险评估
记录谷歌gn编译时碰到的一个错误“I could not find a “.gn“ file ...”
day14--postman interface test
手把手基于YOLOv5定制实现FacePose之《YOLO结构解读、YOLO数据格式转换、YOLO过程修改》
迁移学习——Joint Geometrical and Statistical Alignment for Visual Domain Adaptation
Chapter 09 Use of Performance Analysis Tools [2. Index and Tuning] [MySQL Advanced]
Method Overriding and Object Class
方法重写与Object类
[Redis] Redis installation under Linux
随机推荐
EBS uses virtual columns and hint hints to optimize sql case
DDOS攻击真的是无解吗?不!
【PyQT5 绑定函数的传参】
《.NET物联网从零开始》系列
[Word] #() error occurs after Word formula is exported to PDF
Use of pytorch: Convolutional Neural Network Module
Tree search (bintree)
Greenplum数据库故障分析——能对数据库base文件夹进行软连接嘛?
开篇-开启全新的.NET现代应用开发体验
直播回放含 PPT 下载|基于 Flink & DeepRec 构建 Online Deep Learning
亚马逊云科技携手中科创达为行业客户构建AIoT平台
【存储】曙光存储DS800-G35 ISCSI各映射LUN给服务器
关于#sql shell#的问题,如何解决?
接口自动化测试框架postman tests常用方法
MySQL3
Transfer Learning - Joint Geometrical and Statistical Alignment for Visual Domain Adaptation
HOG特征学习笔记
【TA-霜狼_may-《百人计划》】图形4.3 实时阴影介绍
[Machine Learning] 21-day Challenge Study Notes (2)
记录谷歌gn编译时碰到的一个错误“I could not find a “.gn“ file ...”