我们开始程序一般会用IDE,也就是集成开发环境,比如Visual Studio、Keil、IAR等,IDE的出现极大的解放了程序员的工作,使得程序员不用再去关注过于底层的物理性的操作,而只去关注应用层面的开发,但是也有缺点,就是对于我这种想象力不强的笨程序员来讲,对于一些底层操作,很难直观的去想象。
IDE同城会将编译和链接的过程一步完成,这个合并的过程,就是我们熟悉的IDE中的build,当然也可以单独编译,也就是IDE中的Compile,了解这背后的过程,无疑会帮助程序员更好的理解程序的运行机制。
IDE对程序员隐藏的过程,主要包含4个步骤:预处理(prepressing)、编译(compilation)、汇编和链接(linking),如下图所示:
简单的分析总结:
预编译:就是处理那些源代码文件中以“#”开始的预编译指令,比如#include,#define等,主要处理规则就是
·将所有的#define删除,然后在使用这个宏的地方展开(所以宏只是方便程序员的),
·对于#include则是将那些包含的头文件展开,copy到当前文件中。
·删除所有的注释
编译:就是将上面预编译得到的文件“翻译”成汇编代码。
汇编:注意这里的汇编是将上面的汇编代码再次翻译成机器代码,可执行的代码,每个汇编语句几乎都对应一条机器指令。
(汇编不是翻译成汇编语句,而是机器码)
链接:现在的程序,一般都不是就一条指令语句,都是几百上千行指令,而且是分布在不同的模块文件里,这个也是很正常的,程序员需要将一个复杂的程序项目拆分成很多的模块文件,这样便于实现,也便于维护,这个在人的思维方式中是非常容易理解的,但是我们要知道CPU是个很轴的笨蛋,它是没有思想,不懂这些哲学层面的概念的,它还是要傻傻的按照提前约定好的逻辑来一步步的执行的,其实如果程序完完全全固定,从头到尾都是一根直线方向,没有什么分支或跳转什么的,理论上没有链接也无所谓,但是实际遇到的情况,恰恰是必定会有各种分支和跳转的,比如说调用某个函数,调用某个变量,由于我们在写程序的时候,是很随意的定义函数或变量的,想让CPU聪明的自动找这个函数或变量是不可能的,它太笨了,它需要一根线,一根将所有模块穿起来的线,穿的过程可能是九曲十八弯,但是却是独一无二,没有重叠的,没有编译器以前,如果想要实现复杂的程序功能几乎是不可能的,因为人的精力是有限的,不可能因为一条语句的增加或删减,重新却计算各种变量或函数的地址,所以需要一个带自动计算功能的链接器,毫无疑问这个链接器的实现一定是很复杂的,这个不用太去深究,简单的理解成,链接器是个大的数据库,自动管理所有的数据,任何一个小的改变,都会自动引起这个数据库的更新,这样就实现了,程序员只需要关注应用层面的逻辑就好,链接器会自动的帮着去做 链接管理的。