我们应该知道多少编译器?

时间:2008-12-09 03:27:22

标签: compiler-construction

为了编写更好的代码,深入了解编译器的作用是否值得?

多少就足够了?我不是一个擦洗器,但我在想,了解编译器的运行方式会让我成为更好的程序员。我错了吗?

如果是,您会推荐哪些资源?

13 个答案:

答案 0 :(得分:20)

知道编译器如何优化代码可能不会有什么坏处,但是不要为编译器编写代码,而是写给人们阅读

以更适合编译器的方式编写代码可能会使人们更难以阅读它,现在编译器可能更了解为您优化代码

答案 1 :(得分:10)

在没有任何有效性的证据的情况下,我感觉更好的理解我的代码会发生什么,因为我只知道编译器和一些程序集。您可以通过阅读Jack Crenshaw's Let's Build a Compiler了解很多。

如果您感兴趣,可以查看更复杂的编译器方法。


编辑:值得注意的是,许多不需要“编译器”的问题仍然可以通过编译器方法获得最佳效果。解析任何适度复杂的命令语言都是编译器问题,即使您没有编写可执行文件。


Edit2:许多通常的文本对编译器问题采取了相当抽象的数学方法,这可能会让人感到恐惧或困惑。 Crenshaw教程采用了“开始敲击代码”的方法,该方法由作者更加微妙的理解提供信息。很好的介绍,但如果你认真,你的跟进更正式的研究。

答案 2 :(得分:3)

我教过编程语言和高级编译器。以下是我认为最有用的两个理由来了解编译器的作用:

  1. 如果您不知道编译器在做什么,您可能会无意中编写比预期更昂贵的代码。如果您在不知情的情况下分配内存,则尤其如此。一个典型的例子是在循环中连接字符串,例如,如

    answer =“”

    表示i = 1到n

      answer = answer .. strings[i]    -- .. is string concatenation
    

    此代码是二次的,进行二次分配和复制。坏消息。

  2. 了解编译器的另一个重要原因是,问题通常需要一点语言。如果您对编译器有所了解(解释器在这里同样好,可能更好),那么您可以构建一个小语言。如果您可以选择语言的外观,通常最好让其他人为您构建语言。 Lua是一种特别擅长被其他程序用作组件的语言。

  3. Crenshaw的教程也不错。另一本很好的书,如果你能掌握它,那就是P. J. Brown关于交互式编译器和口译员的书。它已经绝版,但您可能会在库中找到它。

    我会避免编写许多关于编译器的本科教科书。迈克尔·斯科特的编程语言语用学是一本可能对编译器更有价值的胖本科文本。

答案 3 :(得分:3)

我认为它肯定会以一种微妙的方式让你成为更好的程序员。

对其工作原理的一般理解将有助于您更加了解您正在编写的代码。我见过很多经验丰富的开发人员在学习新语言时很难理解一些基本概念。如果您大致了解编译器的工作原理以及(可能更重要的)代码的执行方式,您将更好地理解这些概念。我在谈论堆与堆栈,指针等。

如果您需要编写代码来分析或翻译某些文本,它也可能派上用场。我曾编写过一个程序,将一些sql条件转换为另一种自定义格式,并为它编写一个小解析器,这是最简单,最优雅的方式(或者我认为:))

此外,对编译器的深入理解可能会帮助您专门针对它进行优化,但这可能非常困难,并不总是建议,正如Coobird所说。

答案 4 :(得分:2)

我认为每个程序员都应该基本了解编译器如何将高级代码转换为机器指令,可以执行的优化,内存如何工作以及代码在硬件上的执行方式。我认为有必要了解这一点,以便您更好地了解程序的性能,并且可以帮助您做出更好的实施选择。

您可以实际编写机器代码或确切了解系统使用的虚拟内存架构可能并不重要,但我认为这些概念的基本概念很重要。

修改

例如:C编译器以行主格式将数据存储在数组中,因此您应首先迭代最大维度(最右侧索引)的多维数组,然后继续进行最低维度(最左侧索引)。 Fortran完全相反,以列主格式存储数组。这意味着在Fortran中,您应首先改变最低维度,然后进入最高维度。这将提高代码的缓存命中率,并显着提高大型多维数组的性能。

答案 5 :(得分:2)

您对有效使用调试器有兴趣吗?好的。您是否有兴趣编写可靠或有效的代码?然后是的。

就我个人而言,我比后端更关心后端。我建议编译ARM而不是x86,在这种情况下你不是必须学习汇编程序(我建议编写你自己的反汇编程序),所以如果你使用gcc它有一个反汇编程序,你可以看到你的高级代码做什么来改变最终结果,以及您可以使用编译器选项进行的更改。对于大多数高级语言程序员而言,基于所使用的编译器和命令行选项,相同的代码可能会产生截然不同的结果,这是一次令人瞩目的体验。

对于编译器的中间部分,我建议使用lcc和sdcc。您可能想要也可能不想购买lcc书籍:

[http://www.cs.princeton.edu/software/lcc/][1]

你不需要,源是在网上(以多种形式)。正如sdcc(小型设备c编译器,最初为8051和其他8位微处理器创建的)。我的建议是进入编译器遇到后端的界面,你会发现你的代码已经变成了一系列原子部分,有时反向抛光就好了。 a = b + 7;最终可能会加载常量整数7.从内存中读取变量b到下一个可用的寄存器中。用b添加7加上寄存器并保存在下一个可用寄存器中。将寄存器中的值存储到内存中的位置。

你也可以用gcc做到这一点,但你可能最终意识到gcc并不像你那样伟大。由于语言的数量和后端的数量以及混合中的手数等,它是巨大而复杂的。它确实可以实现,并且适用于拥有专家维护的语言和平台。 gcc可能会告诉你其他人不可能的是,前端的各种语言将归结为一种共同的中间语言,后端会变成每个平台的特定指令。

最后是前端。在大多数情况下,人们使用bison / yacc,这是一个为高级语言创建描述的工具,该工具可以根据您的描述解析用户输入,如果愿意,可以将其转换为这种中间语言。

如果你计划你的爱好或职业与编写软件有关,我会说你必须经过这次练习一次,如果不是很多次。代码的整体质量,代码的可靠性,代码的性能以及编写代码的效率都会受到这些知识的影响。

我会小心使用“不要为编译器编写,而是写给人们阅读”。那里有很多不好的代码,因为这种语句被滥用了。编写可维护性代码会导致必须维护的错误代码。可维护性与可靠性和性能相互排斥。我个人的可靠性和性能比任何大学毕业生都能维护的不良代码要好。

随着时间的推移,您将学习不要为编译器而努力。只是不要浪费你的代码,不要使用该语言的gee whiz功能。如果你需要做额外的研究以找出一些编译器功能,你可以确定世界上大多数人都不理解它,包括那些应该在编译器中实现它的人。因此,您可以预期该功能在编译器之间不能一致地工作,因此您应该首先使用它。这也意味着不要尝试为一个特定的编译器编写代码,不要太依赖gcc及其功能,尝试sdcc和lcc以及microsoft和borland和kiel等。使您的代码干净,简单,可读和可移植。

总而言之,如果您认真编写软件,那么您绝对需要知道编译器的工作原理。 gcc,sdcc,lcc,(以及vbcc,如果你能找到的话)都是免费的,开源的,并提供一种学习经验,可以提高你的编码技能。

答案 6 :(得分:1)

我认为编译器所做的是重要的事情(它创建了一个带有x,y,z特征的解释)。这被翻译成了解你所针对的平台。

它执行该任务的方式无关紧要(除非您当然正在编写编译器)

我们应该了解的关于编译器的最重要的事情是它显示的错误消息。

:)似乎很明显,但我对我遇到的开发人员数量感到惊讶,甚至没有看到编译器输出。

答案 7 :(得分:1)

不要学习编译器,了解他们解决的问题。

答案 8 :(得分:1)

我认为不必了解编译器的工作原理,因为它不断改进编程知识。现在,学习编写编译器(或其背后的原理)恰好是扩展一个人知识的好方法。

如果您有兴趣,我建议您购买龙书,也称为Compilers: Principles, Techniques and Tools。这可能是第一次有点沉重,但它肯定会让你思考。如果你没有完全通过或者卡在某些部件上,我会建议将它搁置一段时间并稍后返回 - 这样可以更容易地完成第二次。

答案 9 :(得分:1)

作为开发人员真正全面发展我认为你应该对编译器有一些了解,以及它们是如何工作的,甚至可能只是想写一个简单的编译器。

但是,对于特定的编译器,大多数开发人员只能知道一件事:编译器切换到输出汇编语言而不是二进制代码。检查输出的汇编语言将告诉您编译器正在做什么来优化代码,并可以帮助您弄清楚如何重新编写代码以使其更好地工作。
此外,还有一个有趣的“程序员练习”来刷新你的低级知识。

答案 10 :(得分:1)

在博文中,Steve Yegge断言所有程序员should know how compilers work。他甚至说:

  

温柔但坚持不懈的执行官   总结:如果你不知道如何   编译器工作,然后你不知道   电脑如何运作。如果你不是100%   确定你是否知道如何编译器   工作,然后你不知道他们是怎么回事   工作

在文章中,他提出了一个需要了解编译器的强有力的论据。他还提供了现实世界的例子列表,其中了解如何解析和分析将是有用的。

答案 11 :(得分:0)

我认为真正重要的是建立一个解释器:它让你更深入地了解编程语言,这就是你所使用的......在方案中,实际上很难做出一个解释器!但实际上,我非常鼓励阅读SICP的部分内容以获得极大的启发。

关于编译器,它更复杂,因为这里的重点是为实际机器获得一些性能/做它。作为程序员,重要的是至少要知道他们在全球范围内执行的任务以及他们何时运行而不是细节,因为现在他们已经发展成为非常复杂的系统,尤其是JIT等...

答案 12 :(得分:0)

至少,您应该在抽象层面熟悉语言功能。如果您不知道变量名是否区分大小写,或者数字是如何转换为布尔值的,那么您甚至可能无法可靠地编写简单的“if”子句。

大多数情况下,我发现关于编译器内部工作原理的任何其他知识都可以帮助我编写更有效的代码。