分享

先有鸡还是先有蛋?C 编译器是用什么语言编的?

 JSharp 2010-04-01
Ken 说,C 编译器是用 C 语言编的。

以下有一些是我自己的猜想:

这并不是说第一个 【C 编译器二进制文件】
就能编译完整的 C 程序。

C 编译器一开始处于创世纪的时代,非常简单,
我猜想肯定是机器语言写的,但是不用很复杂,
只需要最最基本的一点点就够了。

之后 C 编译器开始用 C 语言写了,写完后用
最初的编译器编译,这样新版本的 C 编译器诞生了。

然后再重新添加新的功能,修改编译器源程序,
再用上一个版本的编译器编译最新版本的编译器源程序,
编译后的二进制文件替换上一个版本的编译器二进制文件。

就这样,C 编译器不断得训练自己,使自己的 C 语言
知识越来越丰富,到最后,它完全实现了 C 语言规范,
可以正式发布给大家使用了。

跟人不一样,人学了一点新的语言知识后,很可能
会忘掉,然后再学,反复几下,可能就记得久一点,
C 编译器不同,只要告诉它一次,它就永远记住了。

下面举个例子来说明一下 Ritchie, Ken 他们是如何
训练编译器的。

C 语言中的字符常量及字符串中可以用反斜杠 \ 字符
来转义,比如 \\ 表示 \,\n 表示一个换行符, \t 表示
按一个Tab键产生的制表符。

在引入这个转义机制以前,C 编译器认为
char *a="\\";
这个写法表示由2个反斜杠组成的字符串。

现在改写编译器的源代码为:

...
c = next();
if(c != '\')
return c;
c = next();
if(c == '\')
return '\';
...

用老的编译器重新编译修改后的源代码,生成后的编译器
现在就有能力识别 \ 是转义符了。然后用新编译器编译时,
char *a="\\"; 就是表示由1个反斜杠组成的字符串了。

这个时候,新的编译器反倒不能正确编译它自身的源码了,
因为 '\' 不再表示单个 \ 字符了,c = '\' 就非法了。
所以这时候就要写成

...
c = next();
if(c != '\\')
return c;
c = next();
if(c == '\')
return '\\';
...

然后再重新编译一遍,虽然没有增加新的能力,但是源代码
的表现方式已经彻底改变了。

之后,要增加新的转义项目,比如把 \n 转义为一个换行符。
不是简单地添加一句

if(c == 'n')
return '\n';

就可以的,因为编译器现在还不知道 \n 的意思,所以你
写成 '\n' 并不能转义为换行符。

所以现在只能写成

if(c == 'n')
return 10;

因为换行符的 ASCII 码是10。这样编译器能够接收了。编译完
生成新的编译器后,再修改原来的编译器代码为:

if(c == 'n')
return '\n';

现在编译器就懂了,然后重新编译它自身的源程序。

类似地,要增加别的转义项目,也要如此这般地训练编译器。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多