两年来,我对编译器和编译理论的认识有了长足的进步。回想起两年前懵懂的样子,以及怀着忐忑的心情到香格里拉饭店参加面试的情形,不禁暗呼一声“侥幸”。
那时,我写程序都是用Delphi或VC++这样的IDE,编译就是按个快捷键或点击某个菜单项,编译器对我来说完全是透明的。编译课早就上过了,可惜完全与实践脱钩,所以也忘的最干净,甚至还不如计算理论这样的课记住得多。最近一次公司找intern,我在面试的时候就问了这样几个问题:
VC++使用的编译器[1]的可执行文件的名字叫什么?(cl.exe)VC++的debug build和release build有什么区别?(调试信息和优化的有无)一般来讲,编译器输出的是什么程序?(汇编程序)回答结果很不理想,说明我们的编译课仍然在纸上谈兵。
当初之所以选择编译作为工作方向,是受到一本书——《深度探索C++对象模型》——的影响。那是我在上学期间看过的提到编译器这个词最多的一本书,也让我了解了隐藏在IDE后面的编译器竟然做着如此有趣的事情。在好奇心的驱使下,我把全部砝码压在一份简历上,而且是一个自己并不擅长的方向。所幸在当时的教育背景下我这样的编译水平不能算差的,更幸运的是能被当时多数面试者(包括现在的部门经理)相中,得以实现从事编译相关工作的愿望。加入公司后,完全从零开始,从最基本的论文看起,恶补了一阵。那情形,让我回想起大一上C语言课,第一次用英文教材,几乎每个词都不认识,都要查字典,很大精力被用来克服语言问题。后来经历也很相似,随着阅读越来越顺利,可以把更多的精力集中到问题域中。渐渐地,对控制流、数据流、依赖关系、以及各类优化不再感到陌生,又随着工作地不断深入,对其中某些领域有了更透彻的理解,也感受到了编译领域的博大精深。
现在,从一个程序员的角度来讲,我对编译器的功能有了充分地认识,可以更有效地使用。编译器对我来说已经不是一个具有单一功能的黑盒子,而是一个可以使用不同选项来实现特定需求的工具。但作为开发者来讲,我的水平还很不够,知识面比较窄,有很多需要加强的地方。由于工作内容所限,我对数据流分析和依赖关系的理论和实现了解得比较多,但对它们的应用认识有限,实际上这是一个很好的基础,因为很多优化都是基于数据流分析和依赖关系分析的结果来做的。
从我个人的经验来看,要想成为一个优秀的程序员,必须熟练掌握几种工具,我在提纲上列出来的是一些我接触过的、也是准备在后面的文章中谈到的。熟练掌握的意思是这种工具对你来讲不再是一个黑盒,你必须对这种工具所基于的理论有所了解,甚至要看过特定实现的代码。正则表达式是最恰当的一个例子,只知道它的语法是不够的,只有在了解了正则表达式引擎是如何工作的,才能构造出高效的正则表达式。所以,如果我们能在闲暇之余了解某些优化的原理,甚至看看gcc的实现,会更有利于我们写出高效的代码,这些代码在我们眼中也会显得更加生动。
[1]. 准确地说,是问driver的名字。