前言
大家在学习C语言的时候,相信对编译器这个词并不会感到陌生。我们也会知道编译器编译的过程是:预处理-》编译-》汇编-》链接。这篇文章主要介绍这四个过程中,编译器究竟做了那些工作,它是如何让一份高级程序转换成机器语言的,这个过程我觉得还是很有意思的。
强烈建议大家看一看《深入理解计算机系统》这本书。
本文参考资料《深入理解计算机系统》
一、数据在存储器中以什么方式存在?
我们在敲代码的时候,可以在显示屏上很清楚的看到每一个字符,但是机器也跟我们人类一样,是通过识别不同的字符来获取信息的吗?可以说是也可以说不是。
之所以这样说,是因为机器它的确是通过不同的字符组合获取信息的。但是在它的世界里,它读取到的信息跟我们看到的字符是不一样的,他们读取的信息是二进制信息–一种只有高低电平的电平信息,我们使用0/1来表示,1代表高电平,0代表低电平。
他们之所以能将字符信息转换成电平信息,是因为我们每一个字符,都是通过ASCLL码表表示的,每一个数字都代表一个字符,如下图所示:
例如这段代码,使用二进制表示如下图:
而二进制通过0和1能表示各进制数字,所以从字符转换成二进制数就有了对应,能准确转换。那么字符要真正转换成二进制数据,就需要通过编译器转换。
二、编译的过程
编译器的概念我还没有去了解,目前我的理解编译器就是一个转换的工具,感兴趣的朋友可以自行去进行更深入的了解,我这里只是讲一下编译的过程。
编译的过程如下:
预处理–>编译–>汇编–>链接
1.预处理
在我们的程序代码中,有不少命令是以#开头的,例如#define等。预处理阶段就是对这些命令进行处理。例如我们使用#define 进行宏定义,在预处理阶段就是把代码中的宏进行替换。例如我们使用#include包含头文件,在预处理阶段就是把被包含的头文件信息读取,并插入当前的.c文件中。这样我们就得到了另一个c程序,这个c程序太长以.i为结尾的文件扩展名。所以在预处里阶段完成后,编译器会输出一个.i为后缀的文件。
2.编译
编译就是将上面说的.i文件翻译成汇编语言,即使是不同的高级程序语言(c/c++等),都会在这个阶段被翻译成汇编语言。并输出一个以.s为后缀的文件扩展名。
3.汇编
在这个阶段就是将.s为结尾的汇编语言文件转换成二进制文件,并以.o结尾。
4.链接
这个阶段就是将被调用到的标准库的函数链接到二进制文件中。例如我们在代码中使用到里printf这个标准C库中的函数,这个函数实际存在于一个名为printf.o单独的预编译目标文件中,编译器就是在这个阶段让连接器将这个目标文件并入.o文件中,最终输出一份可执行文件。
总结
有错误的地方请及时指出,共同进步。