我们在把代码以人类能够看懂的形式写好以后,它是不能直接使用的,它需要经过俩个环境,分别是翻译环境和运行环境:翻译环境会将源代码转换成可执行的机器指令,也就是二进制指令。第二种是执行环境,它用于将代码给实际运转起来。那么,我们就按照顺序介绍翻译环境和执行环境吧。

翻译环境

翻译环境由编译和链接俩个大过程组成,而编译又可分为预处理,编译和汇编三个小过程。一个C语言一般由多个.c文件一起构建,多个.c文件皆单独通过编译器以后生成对应的目标文件,一般在window生成的后缀是.obj,而在LINUX中生成的是.o文件,这些生成以后的目标文件和链接库一起经过链接器处理生成最后的可执行文件,链接库是指运行时库或者自己添加的第三方库。如果用图来表示这个环节的话,如下图所示。编译与链接-LMLPHP

接下里具体介绍编译阶段中的分阶段。首先是预处理阶段。

在预处理阶段,编译器会把你写的代码处理为.i为后缀的文件。在这个阶段,它会开始处理那些预编译的指令,具体有以下几点:

1.将所有的#define删除,并且展开所有的宏定义。也就是将替换后的字符替换所有被define的字符。

2.处理所有的条件编译指令,如#if,#ifdef等等等等

3.处理#include预编译指令,将头文件对应的文件还原,被包含的文件若含有文件,也会一直递归处理。

4.删去所有为人类而写的注释,机器不看这些

5.添加行号和文件名标识,便于编译器生成调试信息。

6.保留所有的#pragma的编译器指令。

第二部是编译阶段,这个阶段编译器会将预处理以后的文件进行语法分析,词法分析,语义分析和优化

1.词法分析

该过程会把源代码程序输入扫描器,扫描器的任务就是进行简单的语法分析,把代码中的字符分割成一系列的记号,具体分析以后的记号如下图所示:编译与链接-LMLPHP

2.语法分析

接下来是语法分析器,它会把扫描到的记号进行语法分析,然后生成语法树,语法树主要是是以表达式为节点的树。编译与链接-LMLPHP3.语义分析

接下来是语义分析,这个过程会对上文产生的语法树进行语法层面分析,编译器所做的分析就是语义的静态分析。

接下来是汇编,这个过程汇编器把汇编代码转变为机器可执行之指令,每一个汇编语句都对应着一条机器能够直接读懂的指令。该过程是根据汇编指令和机器指令的对照表一一进行翻译,不会进行指令优化。

翻译环境的最后一步是链接,链接过程包括地址和空间的分配,符号决议和重定义等步骤。编译索要解决的问题是一个项目中多文件多模块之间互相调用的问题。假设我创立了两个文件分别叫data.c.和main.c,然后main.c中需要用到data中的函数add,在前面的步骤由于都是独立进行的,所以无法使用到这个函数,编译器会暂时把这个搁置,在链接阶段链接器会根据名字进行索引,找到相应的函数的地址,然后将原先搁置的地方变成这个地址,对于这个过程就叫做重定义。

执行环境

1.程序必须在内存中工作。在自带操作系统(windows,linux)的设备上直接由操作系统完成。在独立的环境中,程序的载入需要用手工进行操作,如嵌入式设备等等。

2.在完成了上一步后,就直接调用main函数,然后就按顺序执行程序代码。这个时候程序将使用一个运行堆栈,存储函数的局部变量和返回的地址。程序同时也会使用静态内存,存储在静态内存的变量在程序的整个执行过程一直不会改变值。

4结束程序。终止main函数

04-28 05:04