如何用C语言编写C编译器?

75
这个问题可能源于我对编译器的误解,但是让我们来看看…K&R第一版前言中可以找到以下陈述(page xi):
“操作系统、C编译器和基本上所有的UNIX应用程序(包括用于准备本书的所有软件)都是使用C语言编写的。”
(我强调)
这里是我不理解的地方:难道那个C编译器在它能够编译任何C代码之前不必首先被编译吗?如果那个C编译器是用C编写的,那么编译它是否需要一个已经存在的C编译器呢?
摆脱这个无限回归的困境(或者鸡和蛋问题)的唯一方法是,K&R所提到的用C编写的C编译器实际上是使用了一种其他语言编写的已经存在的C编译器进行编译的。用C编写的C编译器接管了以前的C编译器。
还是我完全错了?

4
你可以先用汇编语言或其他方式创建一个程序,一旦完成后,就可以使用它来制作C语言版本的程序,之后也可以制作其他语言版本。 - chris
C语言最初是在B语言中编写的,而B语言则是从BCPL简化而来,而BCPL又是从Algol 60简化而来。我相信B语言可能是使用宏汇编器编写的。 - aoeu256
4个回答

55

这被称为引导, 来自维基百科的引用:

如果需要一种语言X的编译器来获得一种用语言X编写的语言X的编译器,那么第一个编译器是如何被编写的?解决这个先有鸡还是先有蛋的问题的可能方法包括:

  1. 使用语言Y实现语言X的解释器或编译器。Niklaus Wirth报告了他是如何用Fortran写出第一个Pascal编译器的。
  2. 另一种语言Y已经编写了X的解释器或编译器;这就是Scheme通常是如何引导的。
  3. 编译器的早期版本是用X的子集编写的,其中存在其他编译器;这就是一些Java、Haskell和初始的Free Pascal编译器的引导方式。
  4. X的编译器是从存在X编译器的其他架构跨编译而来的;这就是C编译器通常被移植到其他平台的方法。这也是在初始引导之后使用的Free Pascal方法。
  5. 用X编写编译器;然后手动从源代码编译它(很可能是非优化方式),并运行该程序以获得优化的编译器。Donald Knuth将此用于他的WEB可读性编程系统。

如果您感兴趣,here 是Dennis Richie的第一个C编译器源代码。


11

通常情况下,第一个编译器是用另一种语言编写的(在这种情况下直接使用PDP11汇编语言编写编译器,或者对于大多数"现代"语言使用C语言)。然后,使用这个第一个编译器来编写一个用该语言本身编写的编译器。

您可以阅读关于C语言历史的页面。 您将看到它也与UNIX系统密切相关。


4
请注意将1970年的真理转化到今天。GCC已经转向使用C++。 - Marco van de Voort
2
哦,使用C++中的GCC...... 我有一点怀疑(也有些害怕!:-))。 - perror
4
以下是需要翻译的内容:http://gcc.gnu.org/gcc-4.8/changes.html 第一行。GCC 4.8 Release Series Changes, New Features, and Fixes - Marco van de Voort

9
请参见维基百科页面中的“鸡和蛋”部分:
如果需要一种语言X的编译器来获得该语言X的编译器(该编译器是用语言X编写的),那么第一个编译器是如何编写出来的呢?解决这个鸡和蛋问题的可能方法包括:
  • 使用语言Y实现语言X的解释器或编译器。Niklaus Wirth报告称,他用Fortran编写了第一个Pascal编译器。
  • 另一种语言Y中已经编写了X的另一个解释器或编译器;这就是Scheme通常如何引导的方式。
  • 先前版本的编译器是用X的子集编写的,对于该子集存在其他编译器;这就是某些Java、Haskell的超集以及最初的Free Pascal编译器引导的方式。
  • X的编译器是从存在X编译器的另一种架构交叉编译而来的;这就是C编译器通常被移植到其他平台的方式。这也是Free Pascal在初始引导后使用的方法。
  • 使用X编写编译器;然后手工编译源代码(很可能是非优化方式),并运行该代码以获得优化的编译器。Donald Knuth用于他的WEB可读程序设计系统。

Pascal cuoq... 在第一点中,语言Y首先应该有一个编译器,对吧?我认为像Clojure这样的语言就是这样编写的。你能解释一下“手动编译”是什么意思吗? - AV94

6

编译器用它所编译的语言来编写是再普通不过的事情了。实现这个目标的方法之一是使用某种其他语言编写语言L的完整编译器,然后使用L中的编译器重新编写一个新的编译器。更有趣的方法是在其他语言中编写L子集的最小编译器,然后使用该最小子集改进编译器,使其不再那么小,并增加可用的L子集。通过这种方式,可以构建出一个完整的编译器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接