计算机专业必须知道的东西——C语言的发展

概要

在1970s早期,C编程语言是作为新生的Unix操作系统的系统实现语言而设计的。衍生于无类型(typeless)语言BCPL,它进化出了一个类型结构【类型系统】;在弱小的机器上,作为改善简陋编程环境工具的这一创新,它已然成为当今主流语言之一。本文研究它的进化。
NOTE: *Copyright 1993 Association for Computing Machinery, Inc. This electronic reprint made available by the author as a courtesy. For further publication rights contact ACM or the author. This article was presented at Second History of Programming Languages conference, Cambridge, Mass., April, 1993.
It was then collected in the conference proceedings: History of Programming Languages-II ed. Thomas J. Bergin, Jr. and Richard G. Gibson, Jr. ACM Press (New York) and Addison-Wesley (Reading, Mass), 1996; ISBN 0-201-89502-1.

历史背景

1960s晚期,是Bell Telephone Laboratories(贝尔电话实验室)的计算机系统研究(中心)的动荡岁月[Ritchie 78] [Ritchie 84]。计算机被从Multics项目组拖走[Organick 78],该项目是MIT(麻省理工学院)、General Electric(通用电气公司)和贝尔实验室的合作项目。到1969年,贝尔实验室管理层、甚至研究人员都认为,Multics项目不能按期完成并且代价高昂。甚至在GE-645 Multics机器被撤走之前,一个非正式小组——早期由Ken Thompson领导,已经着手一些其它的研究。
Thompson希望按照自己的设计、使用可用的任何方式,创造一个舒适的计算环境。事后诸葛亮地说,他的计划集成了Multics的许多创新方面,包括关于进程的清晰概念——控制块,树型结构的文件系统、作为用户级程序的命令解释器、文本文件的简单表示和访问设备的通用化。他们排除了其余特性,比如对内存和文件的统一访问。此外,开始的时候,他与我们这些俗人遵循[推迟?]着Multics的另一个先驱性(虽然不是原创)的特性,即几乎仅用高级语言来编程。PL/I【Programming Language One,IBM公司在1950s发明的高级编程语言】——Multics的实现语言,不太符合我们的口味,因而我们也使用其他语言,包括BCPL,我们担心【regretted?】失去使用在汇编程序的级别以上的语言进行编程的优势,即容易编写、易于理解。当时我们并未特别关注可移植性,到后来才有了这方面的兴趣。
Thompson面临的硬件环境,即使在那个时代也是又拥挤又简陋:他从1968年就开始使用的DEC PDP-7,只有8K的18bit字(长)的内存,并且没有对他有用的软件。虽然心想着使用高级语言,他还是用PDP-7汇编器编写了最初的Unix系统。刚开始的时候,他甚至并未在PDP-7上编程,而是在一台GE-635机器上使用GEMAP汇编器的一些宏。一个后处理器(postprocessor)生成PDP-7可读的纸带。
这些纸带从GE机器拿到PDP-7上进行测试,直到一个原始的Unix内核(kernel)、一个编辑器、汇编器、一个简单的外壳(shell)(命令解释器)和一些工具(像Unix rm, cat, cp命令)被完成。此后,这个操作系统可以自我支持:可以编写和测试程序,勿需借助纸带,并且程序开发可以在PDP-7上持续进行。
Thompson的PDP-7汇编器在简明性上甚至优于DEC的;它对表达式求值并得到对应的比特流【二进制源代码】。没有库、没有装载器或没有链接器:程序的全部源文件提交给汇编器,而其输出文件(the output file)——有一个固定名字——是可以直接执行的(这个名字,a.out,道出了一点Unix渊源;它是汇编器的输出。甚至在系统有了链接器和有了显式指定另一个名字的方式之后,它仍被保留作为编译器的默认可执行文件(名))。
Unix在PDP-7上首次运行后不久,1969年Doug McIlroy创造了这一新系统的第一个高级语言:一个McClure的TMG实现[McClure 65]。TMG是一种自顶而下,递归降解(top-down, recursive-descent)风格的编写编译器(更一般地,TransMoGrifiers)的语言,它将上下文无关的语法表示法与过程(式程序)元素相结合。McIlroy和Bob Morris使用TMG为Multics编写了早期的PL/I编译器。
受McIlroy重造TMG事迹的刺激,Thmopson认为Unix(当时可能还没有取这个名字)需要一种系统编程语言。经过用Fortran的短暂而受阻的尝试后,他创造了一门他自己的语言,他称之为B。B可被视为没有类型的C。更准确地,它是塞进8K字节内存,经过Thompson大脑过滤后的BCPL。它的名字最有可能表示为BCPL的缩写,尽管另一种理论认为它源自于Bon[Thompson 69],Thompson在Multics的那些日子创造的一门不相关的语言。Bon进而二中其一,可能是以他妻子Bonnie的名字,或者(根据它的操作手册中的一个百科全书般的引用)以一种宗教命名,该教仪式涉及咕隆咕隆的神奇咒语。
一,与C语言相关的语言很多。其中最早的一门语言叫 Algol 60,是 1960 年产生的,它是真正的第一门面向问题的语言。但是这门语言离硬件比较远,所以 1963 年剑桥大学在 Algol 60 的基础上研发出了 CPL。CPL 同 Algol 60 相比更接近硬件一些,但规模比较大,难以实现。1967 年剑桥大学的马丁·理查兹(Martin Richards)对 CPL 进行了简化,产生了 BCPL。BCPL 中的 B 就是 Basic 的缩写,即“简化的”。

二,1970 年,美国 AT&T 公司贝尔实验室(AT&T Bell Laboratory)的研究员肯·汤普森(Ken Thompson)以 BCPL 为基础,设计出了很简单而且很接近硬件的B语言(取 BCPL 的首字母)。B语言是贝尔实验室开发的一种通用程序设计语言。虽然它没有流行起来,但是它很重要。肯·汤普森用B语言做了一件很重要的事情,一直影响至今,即他用B语言写出了世界上第一个操作系统——UNIX 操作系统。

三,1971 年,贝尔实验室的丹尼斯·里奇(Dennis Ritchie)加入了肯·汤普森的开发项目,合作开发 UNIX。他的主要工作是改造B语言,使其更加成熟。

四,1972 年,丹尼斯·里奇在B语言的基础上最终设计出了一种新的语言,他以 BCPL 的第二个字母作为这种语言的名字,即C语言。

五,1973 年年初,C语言的主体完成。肯·汤普森和丹尼斯·里奇开始用C语言完全重写 UNIX,这就是 UNIX 第 5 版。随着 UNIX 的发展,C语言自身也在不断地完善。直到今天,各种版本的 UNIX 内核和周边工具仍然使用C语言作为其最主要的开发语言,其中还有不少继承肯·汤普森和丹尼斯·里奇之手的代码。

六,UNIX 系统是世界上第一个真正的操作系统。由于 UNIX 操作系统是用C语言编写的,而这个系统很流行,于是C语言也跟着流行起来。而 UNIX 操作系统是开源的,所以别人要想学习,就要先学C语言。

七,B语言被C语言改写后,C语言流行了而B语言就被淘汰了。而且后来发现,C语言的确非常好,它是面向过程语言的代表,是有史以来最重要的一门计算机语言。

八,随后又出现了 C++。C++ 是本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)编写的,他也来自贝尔实验室,是C语言创始人丹尼斯·里奇的下属。C++ 就是在C语言的基础上发明的。C++ 进一步扩充和完善了C语言,是一种面向对象的程序设计语言。

后来 Sun 公司又对 C++ 进行改写,产生了 Java。而微软公司发现 Java 很流行,就造出了一个类似的语言——C#。所以 Java 和 C# 都源自于 C++。

以上就是C语言演变的过程。从这个过程我们可以看出,如果以后要学习 C++、Java 或者 C# 的话,那么C语言就必须要学!因为它们都源自于C语言。而且C语言中绝大部分的知识,在 C++、Java、C# 中几乎都会用到。C语言里面有两个知识点是必须要学的,一个是函数,另一个是指针。这两个知识点是整个C语言的主体和核心。而且这两个知识点在其他语言中是学不到的,或者是同C语言中有差别。总之,C语言是它们的“老祖宗”,学习其他语言之前最好要将C语言学好。

起源:这些语言

BCPL是由Martin Richards于1960年代中期,在访问麻省理工学院时设计的;在1970年代早期它被用在几个有趣的项目中,其中包括位于牛津的OS6操作系统[Stoy 72],和施乐公司PARC研究中心的创造性项目Alto的一部分[Thacker 79]。我们熟悉该语言,是因为Richards工作过的MIT CTSS系统[Corbato 62]被用于Multics开发。最初的BCPL编译器被Rudd Canaday和贝尔实验室的一些人们移植到Multics和GE-635 GECOS系统上[Canaday 69];在贝尔实验室的Multics项目奄奄一息的阶段,它成为随后转入Unix的一帮人选择的语言。
BCPL、B和C都归属于以Fortran和Algol 60为代表的传统过程式家族。它们格外地倾向面向系统编程、小巧、描述简洁,而且可被简单的编译器轻易地翻译。它们接近机器,它们所引入的抽象以传统计算机所提供的具体数据类型和操作为基础,它们依赖于例程库以输入输出以及与操作系统的其它交互。尽管不太成功,它们还使用库程序指定其他有趣的控制结构,如协程和过程关闭。同时,它们的抽象层次足够高,足够用心的话,能达到机器间的可移植性。
BCPL, B和C在很多细节上存在语法差异,但总体上它们是相似的。程序由一系列的全局声明和函数(过程)声明组成。BCPL中,过程能够嵌套,但不能引用定义在外包过程中的非静态对象。B和C通过更强行的限制避免了它:基本就没有嵌套过程。每一种语言(除了早期的B版本)都认可(文件的)分别编译,并提供了从指定文件中包含(including)文本的方式。
BCPL中的若干语法和词法机制较B和C中的更优雅和正式。例如,BCPL的过程和数据声明拥有更一致的结构,并且它提供了一套更完整的循环结构。尽管BCPL程序名义上是由分界的字符流构成,聪明的规则使得以每一行结束的语句可以省略其分号。B和C忽视了这种便利,大多数语句以分号来结束。刨除这些差异,BCPL的大多数语句和操作符直接对应B和C中的相应物。
BCPL和B之间的一些结构化的差异源于介质存储的限制。比如,BCPL声明采用这样的形式
let P1 be command
and P2 be command
and P3 be command...

此处的由命令表示的程序文本包含完整过程。这些子声明相互关联而且同时出现,所以名字P3在过程P1内可见。相似地,BCPL能在求得一个值的表达式里包含一组声明和语句,例如
E1 := valof ( declarations ; commands ; resultis E2 ) + 1

BCPL编译器在产生输出前,通过存储和分析内存中该完整程序的解析过的表示,可以容易地处理此类构造。B编译器所受的存储限制决定了一种一次通过( one-pass)技术,由此尽可能快生成输出,而这一语法上的重新设计将这种可能带入到C。
BCPL中少量的、归结于技术问题的讨嫌方面,在B的设计中被有意地避免了。例如,BCPL使用一个“全局向量”(global vector)机制用于在分别编译的程序之间通信。在这种模式下、程序员要显式地将每一个外部可见的过程和数据对象的名字,与全局向量中的一个数值偏移量关联起来;被编译的代码通过使用这些数值偏移量完成链接。B避免了这种麻烦,起初是将整个程序一次性地全部提交给编译器。B的后期实现——C也如此,使用一个传统的链接器来解析分别编译的文件中的外部名字,而不是把指定偏移量的负担推给程序员。
从BCPL到B迁移的某些搞法,源于偏好而且存在争议。例如使用单个=字符代替:=表示赋值的决定。还有,B使用/**/括起注释,而BCPL使用//以注释掉直至行末的文本。这显然是PL/I的传统。(C++重新启用了BCPL的注释方式)【C语言也启用了//注释】Fortran影响了声明的语法:B的声明语句先是一个auto或static这种修饰符,后面是名字列表;C不仅遵循这种风格,还把类型关键字放在声明语句的最前面。
并非Richards的书[Richards 79]规范的BCPL与B的每一个不同都是有意的。我们起步于BCPL的一个早期版本[Richards 67]。例如,在我们于1960年代开始学习它时,从 BCPL的switchon语句跳出的endcase并没有出现,因而B和C中都使用的跳离switch语句的关键字break,只能说是殊路同归而非有意的改变。相对于创建B的过程中产生的诸多语法变化,BCPL的核心语义内容——其类型结构和表达式求值规则——保持不变。两者都是无类型的(typeless),或者说只有单一的数据类型,“字”(word)或“单元”(cell)——一个固定长度的位模式【只有机器字】。这些语言中,内存由这些cell线性数组构成,每一个单元【保存】的内容的含义由所用的操作决定。例如+操作符,使用机器的整数加法指令,将两个操作数简单相加,其它的算术运算也同样不管它们的操作数的实际含义【操作数就是一个01串,不管它是int、char还是位图数据】。由于内存是一个线性数组,就可以将单元的值解释为该数组的索引,而且BCPL为此提供了一个操作符。开始被拼作rv,后为!,而B使用一元*。因此,如果p是这样的单元,保存另一个单元的索引(或地址,或指向它的指针),则*p表示被指向单元的内容,不管*p是作为表达式的值【右值】还是赋值语句的目标【左值】。
因为BCPL和B中指针不过是内存数组的整数索引,对它们进行算术运算是有意义的:如果p是一个单元的地址,那么p+1是下一个单元的地址。这种约定是两种语言中数组的语义的依据。用BCPL编写
let V = vec 10

或用B,
auto V[10];
效果是一样的:命名为V的单元被分配,然后再拔出另一组10个连续单元,而它们中第一个的内存索引被存放在V中。【这不是C的搞法】按照一般规则,B中的表达式 *(V+i)把V和i相加,并指向V后第i个位置。BCPL和B都增加了特别的符号以简化这种对数组的访问;在B中的等价表达式是
V[i]
在BCPL中是
V!i
这种引用数组的方法甚至在当时也不常见;后来C以稍微不同的方式沿用了这一方式。

BCPL,B或C都没有在语言中对字符数据提供强烈的支持;它们都把字符串当作整型的向量[数组]处理,并通过几个约定补充[数组的]通用规则。在BCPL和B中,字符串字面值/文字表示由字符串的字符所初始化的一个静态区的地址,(这些字符)被塞入那些内存单元。BCPL中,第一个被塞的字节包含串所拥有的字符个数;而B,没有该计数而字符串终结于一个特别的字符,在B中被拼写为 `*e’。作出这一改变的部分原因,是避免用一个8位或9位槽(slot)保存串的计数会导致的字符串长度的限制,部分原因是维护该计数似乎,按我们的经验,不如使用一个终结符方便。

BCPL串中单个的字符通常被如此处理:字符串被展开为另一个数组,每单元一个字符,然后再次打包;B提供了相应的例程,但是人们更多地使用其他的库函数以访问和替换一个串中的单个的字符。

计算机专业必须知道的东西——C语言的发展相关推荐

  1. 计算机专业研究生西安就业,计算机专业需要考研吗?毕业之后该怎么发展?

    计算机专业目前是非常热门的专业,无论是考研还是高考,很多人在选择专业就会选择这个专业.这几年互联网的发展势头相当好,尤其是IT行业一直是高薪职业,就业前途非常好.尤其是名校毕业的计算机专业,毕业后后前 ...

  2. 继续教育计算机专业能学到东西吗,继续教育个人学习心得体会

    继续教育个人学习心得体会 当我们经过反思,有了新的启发时,不妨将其写成一篇心得体会,让自己铭记于心,如此就可以提升我们写作能力了.但是心得体会有什么要求呢?下面是小编收集整理的继续教育个人学习心得体会 ...

  3. 音乐对计算机专业的影响,浅析计算机网络技术对音乐发展的影响

    浅析计算机网络技术对音乐发展的影响 发表时间:2016-12-14T11:32:49.970Z 来源:<教育学文摘>2016年12月总第212期作者:王红艳 [导读] 当今,在以计算机技术 ...

  4. 计算机专业c语言挂科怎么办,大学最容易挂科的“学科排行榜”出炉,补考难度很高,你挂了吗?...

    高考是改变命运的独木桥,决定未来发展方向的一次重要的机会,在经历了12年的寒窗苦读之后,学子都希望能够考入一个较好的大学,选择一个好就业的专业,让自己的人生顺顺当当的,但是哪怕是上了大学之后,依旧不能 ...

  5. 大一怎么学好c语言_计算机专业大一学生,应该先学习哪门编程语言

    首先,对于计算机专业大一的同学来说,应该先从C语言开始学起,原因有三个方面,其一是C语言是面向过程式编程语言,比较简单易学,其二是掌握C语言对于学习后续的计算机专业课有较大的帮助,掌握C语言还可以通过 ...

  6. 中专计算机应用专业建设思路,以信息化教学资源建设促进中职计算机专业建设的研究...

    何轩 摘要:随着网络.计算机等信息化技术的发展,中职教育亦渐渐引入全新的技术,以此提高教学水平.计算机专业是一门贴近前沿计算机技术的专业,所以需要立足市场需求,结全新的信息化技术制作出符合要求的教学资 ...

  7. 现在计算机学什么好找工作吗,计算机专业都学什么 毕业好找工作吗

    计算机专业现在是一个比较火爆的专业,毕业之后的发展前景也是很广阔的,因为现在是互联网的时代,所以计算机行业是一个朝阳产业,下面小编为大家提供计算机专业都学什么,毕业之后好找工作吗,希望对大家有所帮助. ...

  8. 中职计算机专业选修课程,《办好中职学校计算机专业的几点思考.doc

    <办好中职学校计算机专业的几点思考 办好中职学校计算机专业的几点思考 温江区燎原职业技术学校 徐永明 [摘要]:计算机是人们生活和工作不可缺少的工具,应运市场而生的职业学校计算机专业近年来却出现 ...

  9. 计算机专业课考研都有哪些,计算机专业考研的课程有哪些

    技校网专门为您推荐的类似问题答案 问题1: 一般计算机专业开设的课程有哪些 java.C++.C语言.SQ.网页设计.操作系统.计算机网络基础.好多的 不过希望希望你只钻研一项最好 不然学不过来 那些 ...

最新文章

  1. Xamarin Android项目运行失败
  2. PL/SQL 中文显示乱码解决方案
  3. 前端(jQuery)(5)-- jQuery AJAX异步访问和加载片段
  4. ionic 完美仿微信摇一摇
  5. 对于58同城自动登陆的补充【主要是代码】
  6. 罚款200元的交通违法行为
  7. php mysql删除失败_php+MySQL实战案例【七】数据编辑、删除
  8. 向程序发送命令失败_java程序员进阶:Redis分布式技术问题集锦
  9. oracle big table1,关于Big_Table脚本的一些有关问题
  10. ++操作你还在使用加锁去保证线程的安全吗?确定不了解一下CAS机制?
  11. SpringBoot基础教程2-1-6 日志规范-使用AOP统一处理Web日志
  12. Codeforces Round #666 (Div. 2) A. Juggling Letters
  13. linux内核之进程管理详解
  14. 混合高斯模型Gaussian Mixture Model(GMM)的EM(Expectation Maxium)求解代码
  15. 深度学习模块介绍 —— Hourglass Module
  16. Android下拉状态栏快捷开关的添加
  17. 超越OCR的富文档内容解析神器LayoutParser
  18. watch中的深度监听
  19. 提交工程到git的分支上
  20. 数据分析学习 excel的骚操作合集(则秀excel课程笔记)

热门文章

  1. App如何在background状态下存活
  2. 哎哟,不错哦之玩乐动物园
  3. 不同分辨率标准,720p 1080p 2k 4k HD FHD UHD
  4. This system is not registered with an entitlement server.
  5. win10内存占用过高解决方案
  6. 俄罗斯军事帝国的衰落
  7. 转:阿里智能音箱天猫精灵发布,联发科成了背后大赢家
  8. Kotlin - 改良构建者模式
  9. 幼儿园案例经验迁移_在建构区中如何将游戏经验迁移为知识经验
  10. 塔望食业洞察|中国有机食品市场研究与发展策略思考