zoukankan      html  css  js  c++  java
  • 世界上第一个C语言编译器是怎么编写的?它为什么能够用C语言编写?

    不知道大家有没有想过一个问题:C语言编译器为什么能够用C语言编写?

    今天小编就带大家一探究竟!


     

    所谓C语言编译器,就是把编程得到的文件,比如.c,.h的文件,进行读取,并对内容进行分析,按照C语言的规则,将其转换成cpu可以执行的二进制文件。

    其本质在于对文件的读入,分析,及处理。这些操作,C语言都是可以实现的。

    所以用C语言来做C语言的编译器是完全可行的。

    但是,历史上的第一个C语言编译器,肯定不是C语言写的,因为在没有编译器时,无法把C语言转换成可执行文件。只要有了第一版其它语言的编译器,就可以用C语言写编译器了。


     

    那么世界上第一个C语言编译器又是怎么编写的呢?

    还是让我们回顾一下C语言历史:

    1970年Tomphson和Ritchie在BCPL(一种解释型语言)的基础上开发了B语言,

    1973年又在B语言的基础上成功开发出了现在的C语言。

    在C语言被用作系统编程语言之前,Tomphson已经使用B语言编写过操作系统。可见在C语言实现以前,B语言已经可以投使用了。

    因此第一个C语言编译器的原型完全可能是用B语言或者混合B语言与PDP汇编语言编写的。

    事实上,B语言的执行效率比较低,但是如果全部用汇编语言来编写,不仅工作量巨大,而且汇编语言的可读性极差,很容易就会出错!

    上一张图大家感受一下这巨大的差别!!!


     

    为了克服这个困难,早期的C语言编译器就采取了一个取巧的办法:先用汇编语言编写一个C语言的一个子集的编译器,再通过这个子集去递推完成完整的C语言编译器。

    大致过程如下:


     

    先创造一个只有C语言最基本功能的子集,记作C0语言,C0语言已经足够简单了,可以直接用汇编语言编写出C0的编译器。

    依靠C0已有的功能,设计比C0复杂,但仍然不完整的C语言的又一个子集C1语言,其中C0属于C1,C1属于C,用C0开发出C1语言的编译器。

    在C1的基础上设计C语言的又一个子集C2语言,C2语言比C1复杂,但是仍然不是完整的C语言,开发出C2语言的编译器……如此直到CN,CN已经足够强大了,这时候就足够开发出完整的C语言编译器的实现了。

    至于这里的N是多少,这取决于你的目标语言(这里是C语言)的复杂程度和程序员的编程能力。

    那么这种大胆的子集简化的方法,又有什么理论依据呢?

    先介绍一个概念,“自编译”Self-Compile。

    对于某些具有明显自举(不知道哪个鬼才起的名字)性质的强类型编程语言

    可以借助它们的一个有限小子集

    通过有限次数的递推来实现对它们自身的表述

    (所谓强类型就是程序中的每个变量必须声明类型后才能使用,比如C语言,相反有些脚本语言则根本没有类型这一说法,比如python。)

    满足自编译这样的语言有C、Pascal、Ada等等,至于为什么可以自编译,可以参见清华大学出版社的《编译原理》,书中实现了一个Pascal的子集的编译器。

    总之,已经有计算机科学家证明了,C语言理论上是可以通过上面的方法实现完整的编译器的。


     

    最后,如果你也想成为程序员,想要快速掌握编程,这里为你分享一个学习企鹅圈子!

    里面有资深专业软件开发工程师,在线解答你的所有疑惑~编程语言入门“so easy”

    编程学习书籍:


     

    编程学习视频:


     
  • 相关阅读:
    linux命令---常用组合
    linux---进程相关的命令
    linux命令---系统监控
    linux命令---find
    linux命令---sort
    linux命令---tar
    linux命令---split
    linux命令---awk进阶
    log4net使用方法
    URL编码:不同的操作系统、不同的浏览器、不同的网页字符集,将导致完全不同的编码结果。
  • 原文地址:https://www.cnblogs.com/mu-ge/p/14031949.html
Copyright © 2011-2022 走看看