一个短暂的周末结束了,代是雄带着意犹未尽的心情早早地来到了公司。自从给唐师傅反馈了自己学习《C语言编程规范》和《数据库编程规范》的学习心得之后,代是雄一直没有收到唐师傅的下一步的学习计划,因此他一直惦记着这件事,想主动询问唐师傅,又不知道这样做是否合适。很多刚进入职场的人都会有这个问题,就是不知道主动向指导老师询问学习计划是否恰当。实际上,在工作中,我们要发挥自己的主观能动性,自己的任何问题都要尽快反馈出来,这样才能让指导老师知道大致的学习情况,才能安排下一步的学习和工作计划。
正当代是雄犹豫着是否应该主动联系唐师傅的时候,后者已经通过邮件向代是雄下达了下一步的学习计划。邮件的内容很简单:请简单描述一下程序编译和链接的过程,要求不要在互联网上查找,在下班之前完成。
看到这个邮件之后,代是雄明白唐师傅是在考察自己对计算机基础知识的掌握程度。不管是计算机组成也好,或者是编译和链接的原理也罢,都和程序设计息息相关,因为只有具备了扎实的理论功底,才能够在软件开发这条路上走得足够远。
我们用高级语言(如C/C++、Java等)编写出来的程序不能被计算机识别,只有经过一定的处理之后才能变为机器码供计算机识并处理执行,这个处理的过程包括预处理、编译、汇编和链接四个步骤。也就是说,对于一个程序hello.c来说,只有经过这四个步骤才能在计算机上运行起来,我们才能够看到程序的输出结果。
第一步:预处理,也叫预编译。这个过程主要处理那些源代码文件中的以“#”开始的预编译指令,比如“#include”、“#define”等,主要处理规则为:1)将所有的“#define”删除,并且展开所有的宏定义;2)处理所有条件预编译指令,比如“#if”、“#ifdef”、“#eif”、“#else”、“#endif”等;3)处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置(注意:这个过程是递归进行的,也就是说被包含的文件可能还包含其它文件);4)删除所有的注释“//”和“/**/”;5)添加行号和文件名标识,比如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号;6)保留所有的#pragma编译器指令,因为编译器须要使用它们。经过预编译后的文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经被插入到文件(如hello.i)中。
第二步:编译。编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件,这个过程往往就是我们所说的整个程序构建的核心部分,也是最复杂的部分之一。编译过程一般可以分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。在Linux下,编译过程相当于执行如下命令:gcc -S hello.i -o hello.s,现在版本的GCC把预编译和编译两个步骤合并成一个步骤,使用一个叫做cc1的程序来完成这两个步骤;也可以使用如下命令:gcc -S hello.c -o hello.s。从最直观的角度来讲,编译器就是将高级语言翻译成机器语言的一个工具。
第三步:汇编。该步骤是由汇编器完成的,它是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令,所以汇编器的汇编过程相对于汇编器来讲比较简单,它没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。对于hello.c来说,汇编过程可以通过调用汇编器as来完成:as hello.s –o hello.o(或者gcc -c hello.s -o hello.o);也可以使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件:gcc -c hello.c -o hello.o。
第四步:链接。源代码被编译成目标代码之后,这个目标代码中有一个问题是:某些变量的地址还没有确定;也就是说,如果目标代码中有变量定义在其它模块,该怎么办?现代的编译器可以将一个源代码文件编译成一个未链接的目标文件,然后由链接器最终将这些目标文件链接起来形成可执行文件。人们把每个源代码独立地编译,然后按照需要把它们“组装”起来,这个组装模块的过程就是链接。链接的主要内容是把各个模块之间相互引用的部分都处理好,使得各个模块之间能够正确地衔接;链接过程主要包括了地址和空间分配、符号决议和重定位等步骤。
“好复杂的过程啊!”代是雄在心里想着,“我们编写的一个简单的’hello world’程序要经过这么周折的处理才能够被机器执行,为什么我们不直接使用机器语言来编写程序,而要使用高级语言呢?”原因是这样的:高级语言使得程序员们能够更加关注程序逻辑的本身,而尽量少考虑计算机本身的限制,如字长、内存大小、通信方式、存储方式等;高级编程语言的出现使得程序开发的效率大大提高,其可移植性也使得它在多种计算机平台下能够游刃有余;有研究表明,高级语言的开发效率是汇编语言和机器语言的5倍以上。
理清了自己的思路之后,代是雄将这个问题的答案写到了一个Word文档中,排好版并检查有无错别字之后便发给了唐师傅。碰巧这个时候唐师傅不在座位上,那么等唐师傅看到代是雄的回复之后,会给出怎样的评价呢?