编译和链接
c
本文章所使用的图片均来在yyds鹏哥
一:???
我们平时使用VS的时候,将写好的代码经调试之后就可以直接达到我们想要的结果,但实际有那么简单吗?
如果你那么想的话,那就大错特错了。
其实我们写好的源代码最先保存在文件中,就好像我们平时用的记事本,这些代码经过一系列变化,最终得到我们想要的结果。
举例:
test.c文件经过翻译环境和运行环境得到了我们最终想要的结果。
二:翻译环境
我们知道源代码计算机是识别不了的,而源代码经过翻译环境就会变成机器可以执行的二进制指令。
那具体的过程又是什么样的呢?
翻译环境包括编译和链接。
可能有小伙伴看到这里疑惑了,什么是链接库???
链接库就是用来存放一些函数的头文件的,比如我们使用scanf,printf函数的时候,为什么我们可以直接使用,就是因为有链接库的存在。
目标文件以 .o 为后缀是在gcc编译器下,在VS编译器下是以 .obj 为后缀。
1:编译
编译分为三个过程,首先是将以 .c 为后缀的源 (头)文件经过预处理,转变成了以 .i 为后缀的中间文件,
然后 .i后缀的文件经过编译变成了以 .s 为后缀的中间文件, .s为后缀的中间文件经过汇编变成了以 .obj 为后缀的目标文件。
1:预处理
在预处理阶段,源文件和头文件会被处理成以 .i为后缀的中间文件。
下面让我们讨论一下经过预处理后文件发生了哪些变化?
变化:
1:会将源代码中的#define全部删除,并且展开所有的宏定义。
2:处理所有的条件编译指令,如:#if,#ifdef,#elif,#else等;
3:处理#include预编译指令,将它所包含的头文件内容插入到该预编译指令的位置,(可能 .c 文件中会多几百行代码)
4:删除所有的注释;
5:添加行号和文件名标识,方便后续编译器生成调试信息等。
6:保留所有的#pragma的编译器指令.
2:编译
编译就是将预处理后的文件进行一系列的:词法分析,语法分析,语义分析及优化,生成 .s 文件,也叫做汇编代码文件
2.1:词法分析:
将源代码程序输入扫描器,扫描器将进行简单的词法分析,将代码中的字符分割成一系列的记号(关键字,标识符,字面量,特殊符号等)
比如:array[index]=(index+4)*(2+6)
2.2:语法分析:
使用语法分析器,将对词法分析产生的记号进行语法分析,从产生语法树,这些语法树是以表达式为节点的。
2.3:语义分析:
语义分析是经过语义分析器来完成的,主要在语法分析后进一步分析 ,编译器所能做的分析就是语义的静态分析,静态语义分析 通常包括声明和类型的匹配,类型的转换等。在这个阶段会报告错误的语法信息。### 3:汇编
汇编会生成以 .obj 为后缀的文件。
汇编这一步主要通过汇编器来完成,汇编器可以将预处理,编译,得到的代码变成机器可执行的指令,每一个汇编语句几乎都对应着一条机器指令,根据汇编指令和机器指令的对照表一一进行翻译,不做指令优化。
2:链接
链接是一个比较复杂的过程,(将多个文件关联起来)链接的时候需要把一堆文件链接在一起才生成可执行程序。
链接的过程主要包括:地址和空间分配,符号决议和重定位(预处理的变化5)。
链接后会生成可执行文件(以 .exe 为后缀)
三:运行环境:
程序运行时主要分为4个步骤:
1:程序载入内存中。在有操作系统的环境中:一般这个过程由操作系统来完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成,
2:开始程序的执行,从main函数开始。
3:开始执行程序代码。这个时候程序使用一个运行的堆栈,存储函数的局部变量和返回地址。程序同时也可以使用静态内存,存储在静态内存中的变量在程序的整个执行过程中一直保留它们的值。
4:终止程序,正常终止main函数,也可能是意外终止。
c
本文章所使用的图片均来自yyds鹏哥