📄 标 题 c语言历史zz.txt
字号:
到1971年我们这个小计算机中心开始有了用户。我们所有的人都希望
更加容易的编写一些有趣的软件。使用汇编器是十分烦躁的,所以B开始
提供了一个关于一些有用的服务例程的小型库,这个库接着被用于越来越
多的新的程序里面。Steve Johnson的第一个yacc版本就是在那个时代的
这些程序中比较著名的之一。
B的问题:
我们最开始使用BCPL以及B的机器都是字编址(word-addressed)的,并且这些
语言只有一种数据类型,那就是“cell”,对应于及其本身的字。PDP-11的出现
暴露出了B语言语法模型的很多不足。首先是他的字符处理机制,这种从BCPL经过
很少变化而来得机制是笨拙的---使用库例程来扩展数组到分立的内存单元然后
在重新打包压缩回去或者是存取并替换单独的字符都开始显示的十分笨拙,甚至
是愚蠢,因为这是一种面向字符的机器。
其二,虽然早期的PDP-11并没有提供浮点计算,但是制造商说明这个将在不
久后的产品中添加进来。浮点操作在我们的Multics的BCPL以及GCOS编译器上已经
被引入了,这是通过定义一些特殊的操作符来完成的,但是这种机制之所以能行
是因为在这些相关的机器上,一个字就能够容下一个浮点数,在我们的16位的
PDP-11上这却是不行的。
最后,B以及BCPL模型意味着这样处理指针:通过定义指针为一个字数组的
索引而强迫指针被表达为字索引。因此,每个指针引用都产生一个运行时间的向
硬件需要的字节地址的转换。
由于这些原因,一些机制比如处理字符和字节地址以及为即将到来的浮点数
处理做准备看起来是有必要的。而其他方面,特别是类型安全和界面检查,在那
个事后还没有显示出其后来的重要性。
和这些问题一起的还有B语言本身。B编译器的“threaded code”技术产生
程序和相应的汇编语言程序相比实在是太慢了,基于这个原因我们对使用B来对
操作系统以及一些系统机制重新编码的做法大打折扣。
1971年我开始扩展B语言,增加字符类型,同时也把B的编译器修改为生成
PDP-11的机器指令而不是原来的threaded code。因此可以说,从B到C的转变和
创建一个有能力生成与汇编语言相比足够小足够快的代码的编译器是同一个时间
的事情。我称这个稍稍扩展的语言叫“NB”,也就是“new B”。
早期的c
NB存在的如此之短以至于没有完整的关于他的描述。他提供了一些简单的类型:
int,char,以及int,char数组和指针。典型的声明是这样的:
int i,j;
char c,d;
int iarray[10];
int ipointer[];
char carray[10];
char cpointer[];
关于数组的语法和B以及BCPL保持了一致:iarray,carray的声明分别产生一个内存
单元,这个单元分别被初始化为连续的10个整数和10个字符的第一个元素的指针。
而指针ipointer,cpointer声明的时候则不提供类似上10的尺寸,从而用以说明不必
自动分配空间。在过程当中,指针的解释和数组变量的解释相同:指针的声明和
数组的声明都创建一个单元,而他们的不同仅仅在于在前者程序员被期望给这个单元
赋予一个指针值,而后者的这个工作则是由编译器自动分配空间来初始化完成的。
在数组和指针名字中(也就是上面分配的那个内存单元中)存储的值是机器地
址,以字节为单位,并在内存中有对应的存储区域。因此,通过指针的间接引用不会
导致运行时间的指针的从字偏移到字节偏移的转换。另一方面,数组下标以及指针的
运算对应的机器代码将和他们所代表的具体的数据类型有关了,具体一点,为了完成
iarray[i]或者ipointer+i的引用就必须在对应的基址上加上i倍所使用的对象的数据
类型的大小。
这些语法很容易的就从B转换了过来,我也在这些方面花了几个月的时间来不停
的实验。当我试着扩充类型,特别是结构体类型的时候,一些问题就出来了。结构体
看起来可以直觉上的映射到物理内存中去,然而如果结构体中包含了数组,就没有一
个好的地方来存放这个隐藏的指向数组基址的指针,也没有一种好的办法来初始化他。
例如,早期的UNIX系统的目录项可以用C描述如下:
strucr {
int inumber;
char name[14];
};
我所希望的结构体不仅仅是指一个抽象的对象,而且应该是一个能够从目录里面读取
的bit集。编译器在哪里隐藏这些语法上需要的name呢?即使结构体被考虑得更加的
抽象而使得这个指针可以隐藏起来,但是当分配一个更加复杂的对象的时候,合适的
初始化这些指针仍然是一个技术难题---这些复杂的对象可能是包含有数组的结构体
有包含了结构体,而这种包含可以达到任意的深度。
而这些问题的解决构成了从无类型的BCPL到有类型的C的变化过程的至关重要的
环节。这些解决办法消除了这些指针的实际的存储,取而代之的是当数组在表达式
中被引用的时候才创建这些指针。这些在今天的c中仍然保留的规则是说:当数组出
现在表达式的时候,数组的值转变成为了指向构成数组的第一个元素的指针。
这个改变尽管改变了原来的语法,但是还是能够使当时已经存在的大多数B代码
能够继续工作。而有一些B和BCPL程序通过改变数组名字的值来重新对齐数组,这些
程序在C中是没有意义的,但是很容易就可以被修改过来。更加重要的是,这门新的
语言保留了和原来数组语法的一致的和可以运作的解释,并且为更加全面的结构体
类型敞开了大门。
第二个区别C和他的前身的创新是更加丰富的类型结构以及这些类型的语法声明。
NB提供基本的数据类型int,char,以及他们的数组和指针,而再也没有其他的了。我
们需要更完善的通用性:给定一种数据类型,就能够描述一种新的类型来代表这种给
定的类型的数组,也应能够从函数中返回这种类型,以及能够描述指向这种类型数据
的指针。
对上面提到过的类型,已经有了一套办法来描述这些提出的对象:数组,访问函
数,使用指针的间接引用。类似的原因导致了相应的一些名字的声明语法,而这些
语法则反映了这些名字在表达式中出现的典型位置。因此,
int i,*pi,**ppi;
声明了一个整数,一个指向整型变量的指针,以及一个指向这样的指针的指针。这些
声明语法则反映出i,*pi,**ppi在表达式中都代表一个整数值。类似的,
int f(),*f(),(*f)();
则分别声明了分别返回整数的函数,返回整型指针的函数,和一个返回整数的函数
的指针;
int *api[10],(*pai)[10];
则分别声明了一个整型指针数组和一个指向整型数组的指针。所有的这些变量的声
明都和变量在表达式中的使用方法类似,而这种表达式的类型就是声明的最开始的
那个东东。
c所采用的这种类型书写办法很大程度上归功于Algol 68,尽管它并不是和Algol
的拥护者所愿望的一样。我从Algol上所获得主要思想是基于原子类型(atomic types)
的,可以被集合成数组的类型结构,指针,函数。Algol 68的联合和casts(??)的概念
也对后C中出现的相应的东东有所影响。
创建了类型体系,以及相关的语法以及这个新的语言的编译器之后,我感到这个
新的语言应该设计一个名字了。NB看起来不够独特,所以我决定继续使用单个字母的
风格并且称之为C,而这个C代表的是字母表顺序还是在BCPL中的顺序我也搞不清出了。
新生的C
当这门语言被命名之后很快就发生了变化,例如引入了&&和||操作符。在
BCPL和B中表达式的取值取决于上下文:if和其他的条件语句把表达式和0进行
比较,而在这些语言中给予and(&),or(|)操作符以特殊的解释。在普通的情况
下,他们是位操作,但是在B语句:
if(e1 & e2) ...
编译器对e1取值,如果非零再对e2取值,如果仍然不是零,详细的描述就取决
于if语句。“需求”在e1,e2的&和|操作符上递归下降处理(??)。这些在
真值上下文("truth-value" context)中的Bool操作符看起来是需要的,但是
这些操作符的重复使用(overloading)导致其难于理解和使用。在Alan Snyder
的建议下,我引入了&&和||来使这种机制更加的清楚明了。
它们的后来引入解释c的优先级规则的一些不合适的地方。在B中使用
if(a == b & c) ...
来检查a等于b或者c非零。在这个条件表达式中&比==的优先级更低。在将B转变
到C后,便希望在这个表达式中使用&&来代替&来消除原来的麻烦,我们决定
保持&相对于==的优先级,并且使得&&的优先级稍微比&低。今天看来好像改变&
和==的优先级关系将更加的合适,这种改变可以简化c的一个习惯用法:使用
mask来测试另外一个值,我们会这样书写
if((a&mask) == b) ...
然而内层的那个必须的括号却是我们很容易遗忘的。
在1972年到1973年,c语言发生了很多的改变,而这其中最为重要的是预处
理程序,这个一部分是由于Alan Snyder的促进,同时也是意识到BCPL和PL/I上
已有的文件包含机制十分的有用。最早的版本提供的机制十分的简单,只是提供
了文件包含和简单的字符串替换:#include和没有参数的#define宏。不久以后
这个得到了扩展,开始有了有参数的宏替换和条件编译,这些大多数是由Mike
Lesk,John Reiser完成的。预处理器在最开始被认为是语言本身的可选的附属
品。实际上,在很多年里,除非在程序的开始有明显的标志否则它是不会被调
用的。这种态度保持着,这就解释了早期的预处理器的语法的不完整以及在早
期的语言手册里面没有对预处理器的精确的描述。
标准化
到了1982年,C语言需要标准化已经成为一个共识。K&R的第一版,作为当时被认为最
接近标准的版本,已经不能描述实际中使用的语言。特别地,它没有提到void和enum类
型。虽然它预言了对structure的实现,语言对structure的具体支持是在其出版之
后的事。尽管AT&T发布的另一个编译器体现了这些变化, 而且大多数并非基於pcc的
编译器也很快吸收了这些新特性,但缺乏一个对C语言完整权威的描述的问题并没有
得到解决。
由於K&R在语言的许多细节上也没有达到足够精确的要求,把pcc作为参照编译器的
做法逐渐不大可行了。他甚至没有体现出K&R所描述的语言本身,更不必说后来的扩
展版本了。最后,C 开始被逐渐应用到政府和商业使得官方标准的正式出版变得重
要。 因此 (在M,D.McIlroy的敦促下),本着建立一个C标准的目的,ANSI于1983年
夏天成立了一个在CBEMA指导下的X3J11委员会。该委员会与1989年底发布了ANSI89报
告,随即,该标准被ISO接纳为ISO/IEC9899-1990。
从一开始,X3J11委员会对C语言及其扩展进行了广泛细致的考察。让我十分满意的
是,他们很认真地为了这样一个目标而努力:"为C程序语言建立一个清楚,
consistent,
无歧义的标准, 从而系统地阐述对公认的现有的C定义,提高用户程序的可移植性
" 显然他们知道仅仅靠发布标准并不能带来根本的变化。
X3J11 对C语言所引入的真正重要的改变只有一处, 即参考C++[Stroustrup86]的做
法, 在函数原型 (signature) 中增加了形参的类型说明。
另外, X3J11还引入了一些细小的改进。比如说,增添了类型描述字const和volatile,
在类型提升的规则上有少许变动。 但是,标准化并没有改变C的特性。
而且新制定的C标准没有试图去正式地制定C的语义,因此在细节处仍然存在争议。
然而它的出现成功地解决了自C诞生以来在使用中出现的变化。而且足够精确使得
实现。
因此,C的核心部分在标准化的进程中保持不变。C标准的出台与其说是新的发明不
如说是一次更好更仔细的修订。大部分重要的修改发生在语言的外层:
预处理器和库函数。 预处理器主要是执行宏替换的功能,使用着与语言其他部分截
然不同的惯例。它与编译器之间的交互在这之前从没有得到很好的描述。
X3J11试图解决该问题。显然,结果比K&R第一版给的解释好得多。 除了更全面之外,
他还提供了一些仅在一些实现中出现的操作比如记号连接。
X3J11相信对标准C函数全面细致的描述与对语言的共作同等重要。C语言本身并不提
供输入输出以及其他与外界交互的手段。他依赖与一套标准函数。在
K&R面世的时候,C被认为是UNIX系统编程语言。 虽然我们提供了可以被容易地移植
到其他平台的函数例程,UNIX的支持是不言理解的。因此,X3J11 委员会投入了大
量时间用于设计和文档化一套库函数从而可以用于所有的一致实现里。
在标准化的过程中,X3J11目前的活动局限于解释现有的标准。值得一提的是,NCEG(Num
erical
C Extensions Group), 一个最初由Rex Jasechke发起的非正式小
组被正式接受成为X3J11.1的一个分组。他们继续考虑对C的扩充。
从其名字可以看出,主要的扩充着眼于使C语言更适合数值计算
的需要。比如,可动态分配的多维数组,对......
演变
Successors:
尽管比不上Pascal语言, C语言乃至B语言都有若干个从其直接繁衍而生
的分支。有一支的发展历史甚至早于C的诞生。Steve Johnson于1972年曾赴University
of Waterloo做访问教授,B语言也随他到了加拿大,在那里的Honeywel机器上备受
欢迎,其后还衍生出了Eh和Zed。
当1973年他回到Bell Labs时,他发现B语言已经在其故乡演化成了C语言,
连他的Yacc程序也被Alan Snyder用C语言重写。
C语言更近一些的分支里包括Concurrent C, Objective C, C*以及C++。
而且许多编译器还采用C语言作为其编译阶段的中间语言。这其中包括C的直接分
支
C++以及独立发展的语言Modula 3和Eiffel
(待续...)
--
我是Daizi
※ 修改:·lkm 於 07月26日10:28:39 修改本文·[FROM: 202.38.79.187]
※ 来源:·瀚海星云 bbs.ustc.edu.cn·
--
不用C++,不学Java,
用C创造我们的程序世界。
※ 来源:·BBS 水木清华站 smth.org·[FROM: 211.71.15.*]
令狐冲精华区搜索引擎 范围 全站 CProgramming版 [百宝箱] [返回首页] [上级目录] [根目录] [令狐冲精华区搜索] [返回顶部] [刷新] [返回]
+ - R
水木社区 → C程序设计语言 → 精华区文章阅读
CProgramming 版 (精华区)
发信人: hagadorn (不要抱怨), 信区: CProgramming
标 题: C语言
发信站: 水木社区 (Fri Jan 6 14:16:37 2006), 站内
维基百科,自由的百科全书
跳转到: 导航, 搜索
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -