目录
今天我们学习的是C语言如何转化成可执行文件的编译过程,以及转化过程中各个阶段都做了什么。
语言分类
在开始前,我们需要先大致了解一下计算机编程语言的发展。
从计算机诞生开始到今天,计算机语言的发展大致经过了 机器码、汇编语言 以及如今的 C,C++,python 等高级编程语言 三个阶段。
机器码,就是我们熟知的二进制 0 和 1,是机器所能识别的语言。
汇编语言,通过加入助记符来帮助早期程序员开发机器码。
编程语言,像在前面提到的几种都有各自擅长的领域,帮助程序员开发各种各样的功能。
作为今天正题的C语言和其它编程语言有本质上的不同,作为编译型语言的C能够通过编译直接被计算机CPU识别并执行;而其他像java这样的解释型语言需要经过转化之后再由解释器一句一句翻译给CPU执行。
打个比方来讲,C语言就像两个中国人在交流,而其它解释型语言就像和外国人之间需要翻译设备来沟通。两相对比之下,自然是能直接和CPU沟通交流的C语言执行效率高,因此在嵌入式中使用的语言一般也都是C语言。
编译过程
下图为C语言在Windows系统上的编译过程。
1.预处理:处理#开头的预处理指令,生成经过宏替换的源文件。(.c->.i)
在这个过程中,编译器做了如下处理:
宏定义展开:所有使用宏的地方都会替换成宏定义的内容;
头文件插入:使用include插入的头文件会转换成这个头文件内的代码插入该位置;
条件编译替换:根据条件编译选择性的保留和删除代码。
2.编译:将预处理后的源文件翻译成汇编文件。(.i->.s)
在这个过程中,编译器会对代码结构进行优化,以提高代码执行效率。比如switch在不同的情况下所采取的代码结构都不相同。
3.汇编:将汇编文件转换为目标文件。(.s->.o)
在这个过程中,项目下所有参与编译的源文件都完成了转化为机器码的过程。
4.链接:将目标文件与库文件链接,生成可执行程序。(.o->.exe等可执行文件)
到这个步骤,前面转化完成的所有机器码文件以及所需的库文件都会被组合在一起,形成完整的程序,可以被执行。