,出自一个菜鸟的提问:“C语言本身是用什么语言写的?”换个角度问,其实是:C语言要运行,必须先编译。那么C语言的编译器从何而来?它是用什么语言写的?如果是用C语言本身写的,先有蛋还是先有鸡?1让我们假设世界上没有编译器,从机器语言开始,看看有什么用。机器语言可以直接由CPU执行,无需编译器。然后是汇编语言。汇编语言虽然只是机器语言的助记符,但也需要编译成机器语言才能执行。没办法用机器语言写这个第一个编译器(以后不会用到)。当汇编语言的问题解决了,就向前迈进了一大步。这时候就可以用汇编语言来写一个C??语言的编译器。我们说这就是C编译器的始祖。有了这个祖先,你可以编译任何C语言程序。是否可以用C语言本身编写一个编译器?跟老祖宗编译就行了。OK,折腾了这么多层终于搞定了一个C语言写的编译器,真是够麻烦的。这时候,前面汇编写的C语言编译器就可以丢弃了。当然,如果在C语言之前已经出现了其他高级语言,比如Pascal,那么你可以用Pascal写一个C语言的编译器。据说第一个Pascal编译器是用Fortran编写的。作为第一个高级语言Fortran,它的编译器应该是用汇编语言编写的。2关于编译器,这里有一个有趣的传说:传说Unix的发明者之一KenThompson大摇大摆地在贝尔实验室的任何一台Unix机器上,输入他的用户名和密码,然后他就可以root登录了.登录!贝尔实验室人才济济,其他一些大牛发誓要找出这个漏洞。他们通读了UnixC的源代码,终于找到了可以登录的后门。清理后门后,编译Unix并运行,但Thompson仍然可以登录。。有人认为可能是编译器出了问题,在编译Unix的时候植入了后门,于是用C语言重新写了一个编译器,用新的编译器重新编译了Unix。现在世界终于太平了。.但是还是不行,Thompson还是可以root登录,真是郁闷啊!后来Thompson自己解决了这个秘密,是第一个C语言编译器出了问题,当然,在编译Unix源代码的时候,这个编译器会植入Backdoor,这还不够。更何况,如果你用C语言写一个新的编译器,它必须被编译成二进制代码。用什么编译它,只有Thompson写的第一个编译器才能编译它,嗯,你写的编译器会被污染,如果你的编译器编译Unix,也会植入后门:-)说到这里,我想起了几年前的XcodeGhost事件。简单的说就是在Xcode(非官方渠道下载)中植入木马,让XCode编译出的iosapp全部被污染,这些app可以被黑客用来做非法的事情。虽然这个XCodeGhost远远落后于Thompson,但是它提醒我们,在下载软件的时候,一定要走正规渠道,从官网下载,寻找网站的HTTPS标准,甚至校验校验。3有人会问:我用汇编写一段HelloWorld很麻烦,但是有人可以用它来写一个复杂的编译器吗?这可能吗?当然有可能。第一代Unix开发的时候,还没有C语言,KenThompson和DennisRitchie在汇编中一行行敲掉了Unix。WPS的第一个版本是求伯君用汇编写的,TurboPascal的编译器也是Anders用汇编写的。高手的能力,非一般人所能想象。对于编译器,也可以“滚雪球”式发展:仍然以C语言为例,第一个版本可以先选择C语言的一个子集,比如只支持基本数据类型、流程控制语句,函数调用...我们称这个子集为C0。然后用汇编语言写一个编译器,只处理这种语言的子集C0,这样写起来就容易多了。C0语言可以工作,然后我们扩展这个子集,比如添加struct,pointer...,调用新的语言C1。那么谁来编写C1语言的编译器呢?自然是C0。等到C1可以工作了,再扩展一下语言特性,用C1写个编译器,得到C2。然后是C3、C4……最后是完整的C语言。这个过程叫做bootstraping,中文叫做bootstrapping。
