📖程序的两种环境
在ANSI C的任何一种实现中,都存在两种环境
- 翻译环境
- 执行环境
- ANSI就是美国国家标准协会的简称,而ANSI C就是美国国家标准协会创立的一套C标准,该标准于1989年完成,这个版本的语言经常被叫做ANSI C有时也称为C89。
🔖翻译环境
在这个环境下源代码被转换成可执行的机器指令。我们平时用VS等工具写出来的源代码都是由字符组成的,只有我们人才能读懂其中的意思,机器是不能直接读懂的,机器只能执行二进制指令,因此就需要把我们写的源文件变成机器指令。而我们写的以 .c 结尾的源文件就是经过翻译环境才得以变成以 .exe 结尾的可执行程序(里面包含的就是可执行指令)。
在VS中由源代码生成一个可执行程序的过程如下图所示:
如上图所演示的,VS2019其实就充当了翻译环境,VS2019是一种集成开发环境。
🔖执行环境
执行环境是用于实际执行代码的。
📖详解翻译环境
编译和链接是翻译环境的两大组成部分,编译环境又细分了预编译、编译、汇编三个小部分,下面我用一张图来展示它们之间的关系。
注意: 上图仅仅展现了它们之间的包含关系,并没有反映出它们的执行顺序,正确的执行顺序是:预编译、编译、汇编、链接。
🔖从人的角度去看编译链接
作为程序员我们只需要将写好源代码交给编译器最终就会得到我们想要的结果,我们无需关心编译器到底进行了哪些操作。具体的过程是:编译器会对我们写的每一个源文件进行单独处理得到一个目标文件,再经链接器把这些所有的目标文件链接到一起,最终得到一个可执行程序
其中链接库就是指将库文件编译后打包为一个二进制文件,这些二进制文件会在程序调用的时候加载到内存。
如上图,此时我们的工程下由两个源文件,分别是text.c和add.c,在生成解决方案后,我们可以在相应的路径下看大它们分别对应的.obj文件。
了解了从人的角度去看编译链接接下来就让我们深入计算机的底层去看看编译链接的“庐山真面目”。
🔖预编译
为了更加直观的展示编译过程的细节,后面我将利用gcc这款编译器进行演示
首先创建一个text.h文件和一个text.c文件,如下图所示:
要得到预处理后的文件需要用下面这条命令:gcc -E text.c -o text.i
- gcc表示用gcc这个编译器
- -E表示执行完预处理就停止下来
- -o text.i表示生成一个text.i文件来存放预处理后得到的结果
- 通过对比,我们可以发现text.i文件相对于text.c文件主要发生了以下几个方面的改变
在text.i文件中把text.h文件中的内容拷贝了过来。
其次在text.i文件中对#define定义的标识符常量进行了替换和删除。
注释的删除。
为什么会出现这种结果?因为#include和#define都叫做预处理指令,跟预处理指令相关的操作都会在预编译阶段做处理,并且这些处理都是一些文本操作(内容的拷贝、宏的替换和删除、注释的删除)