编译与链接(详细图解)
编译与链接(详细图解)
目录
一.翻译环境与运行环境
二.预编译
三.编译
四.汇编
五.链接
一.翻译环境与运行环境
从写代码到输出结果,存在两个不同的环境,即翻译环境和运行环境。在翻译环境中将源代码转化为可执行的机器指令(二进制指令),在执行环境中才是实际执行代码。其中翻译环境又包括编译和链接两大过程,编译包括:预编译,编译,汇编。运行环境就是生成可执行程序,而后产生输出结果。下图大致能展现整个过程。
在C语言的项目中,多个.c文件每个单独经过编译器,各自生成对应的目标文件,也就是.obj为后缀的目标文件(Linux中为.o),多个目标文件和链接库一起经过链接器处理得到可执行程序,这就是C语言中编译链接的基本过程。而如果将这些过程再展开详细解读,请看下图:
二.预编译
在预编译(预处理)阶段,源文件以及头文件都将处理成.i为后缀的中间文件。在此阶段,所有的#define将被删除,并且展开所有的宏定义;处理所有的条件编译指令(如 #if,#ifdef等);处理#include预编译指令,将包含的头文件内容进行插入;删除所有注释;添加行号和文件名标识等操作。
此时的.i文件已经 不再包含宏定义,所有的宏都已经被展开,因此如果想查看宏定义或头文件是否包含正确时,可以查看预编译后的.i文件来确认。
三.编译
编译过程就是将预编译后的文件进行词法分析、语法分析、语义分析及优化,生成汇编代码文件。
词法分析:将代码语句的每个词进行定义分析,如arr[index]中,arr是标识符,[是左方括号,]是右方括号,index是标识符,如此将每个词进行分析。
语法分析:对扫描产生的记号进行语法分析,从而产生语法树。下图形象地展现了语法树的实现,语法树的每个节点都是表达式。
语义分析及优化:即对表达式的语法层面分析,这个阶段会报告错误的语法信息。此时进行语义识别,在上图语法树的基础上加以类型区分匹配。
四.汇编
汇编器是将汇编代码转转变成机器可执行的指令,每⼀个汇编语句几乎都对应⼀条机器指令。就是根据汇编指令和机器指令的对照表⼀⼀的进行翻译,也不做指令优化。
五.链接
链接是一个复杂的过程,链接需要将多个文件链接在一起生成可执行程序。链接库是指运⾏时库(它是⽀持程序运行的基本函数集合)或者第三方库。
如上图所示的C项目中的两个.c文件,每个源文件经过独自编译后都生成了自己的.o文件,但正是因为如此,在 test.c中并不知道def.c中函数和全局变量的地址,因此将目标地址搁置,等进行链接后再进行修正,得到真正的地址。这个步骤叫做重定位。