💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶🔹C++🔹Liunx
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍
文章目录
一、程序的执行总体描述
无论是在Windows还是Linux中程序的执行步骤都是相同的,只是一些文件的后缀可能不同。
通过下图可以很清晰的看出之间的包含关系。
- 总体上来说程序的执行就是【翻译环境+运行环境】
- 翻译环境又分为【编译+链接】
- 编译又分为【预处理+编译+汇编】
二、gcc是什么?
gcc
英文全名为(GNU Compiler Collection),编译器。包含了编辑、编译、链接、调试这些功能。
早期的gcc编译器主要用于C语言编译,但是经过几十年的发展,gcc编译器可以用于多种语言的编译,例如C++、Go等目前较为主流的语言。
熟悉gcc编译器是对于我们开发C/C++程序的底层基本功,虽然目前各厂商的开发IDE已经非常智能,从某种程度上已经把程序员从底层代码的编译、部署等工作解放出来,但是如果需要开发大型C++项目或者对于编译过程进行优化,那么gcc编译器是需要进行了解和深入的
三、、linux下程序的执行深入探究
那么我们接下来就来详细学习一下在Linux下,一个程序的执行过程。
1.预处理
预处理阶段执行的事情如下:
- 1️⃣ 头文件的展开
- 2️⃣ 宏定义的替换
- 3️⃣ 去注释
- 4️⃣条件编译的执行
对应的gcc指令:
gcc -E file.c -o file.i
【-E
】:表示是让 gcc 在预处理结束后停止编译过程
【-o
】:表示输出到指定文件
【.c
】:以.c结尾的文件表示源程序;
【.i
】:以.i结尾的文件表示已经过预处理的C原始程序
2.编译
功能:C语言——>汇编语言
此时的test.s
文件就是一个汇编语言
的文件
在编译阶段会执行以下四件事
- 1️⃣语法分析
- 2️⃣词法分析
- 3️⃣语义分析
- 4️⃣符号汇总
对应的gcc指令:
gcc -S file.i -o file.s
【-S
】-S表示只进行编译而不进行汇编,生成汇编代码
【.i
】.i结尾的文件表示源程序;
【.s
】.s结尾的文件表示经过编译生成的汇编代码
3.汇编
功能:汇编语言——>可重定位目标二进制文件
此时的test.o
文件就是一个二进制的文件
- 1️⃣将汇编指令转换为二进制指令【需要特定的文本阅读器readelf】
- 2️⃣形成符号表
对应的gcc指令:
gcc -c file.s -o file.o
【-c
】:-c表示是gcc编译到目标代码,注意是小写c
【.s
】:.s结尾的文件表示经过编译生成的汇编代码;
【.o
】:.o结尾的文件表示经过编译生成的二进制文件
4.链接
(1)什么是链接?
链接(linking)
是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行。
(2)为什么需要连接?
每一个源文件(就是.c文件,上图中的程序1)都有对应的零碎文件(就是.h文件),通过预编译(通过#include实现)把.c和.h文件整合成一个组合C文件,这个组合C文件的扩展名为.i。把组合C文件编译成汇编文件.s,目标文件为机器指令(放在一个.o文件当中),单个目标文件是不能工作的,因为各个目标文件是相互支撑工作的。
把各个目标文件整合的过程就叫链接过程。
【-o
】:将test.o文件链接生成test.out文件
功能:可重定位目标二进制文件——>生成可执行文件或库文件
此时的test.out
文件就是一个可执行
文件
🚩Windows中可执行文件是以[.exe
]结尾;而Liunx中可执行文件是以[.out
]结尾
链接阶段执行的
- 1️⃣合并段表。在汇编结束生成的obj文件,内部其实会被划分为几个段,在链接过程中会将这些段进行合并。
- 2️⃣符合表的合并和重定位。在链接过程中,我们会对不同的符合分配一个相应的地址。而有的时候,一些符号在它所处的文件中并不存在,存在于另一个文件中,这时候我们会提前分配一个无意义的地址。在合并之后,会将合法的地址重新定位覆盖原来无意义的地址。
四、🕔记忆:
命令选项:-E -S -c
文件后缀:.i .s .o
五、完整流程实例
通过预编译、 编译、汇编、链接最终生成了绿色高亮的可执行文件
六、一步直接生成可执行文件:
gcc 源代码文件名 -o 可执行文件名(自取)