如果有人说“我想要一种语言呮需对它说我要干什么就行”,给他一支棒棒糖好了1
什么是C语言?它是20世纪70年代初期在贝尔实验室开发出来的一种广为使用的编程语言这一简单回答显然没能传达出C语言的特别之处。不过别急在深入学习这门语言之前,让我们先来回顾一下C语言的起源、设计目标和这麼多年来的发展(?1.1节)我们还将讨论C语言的优缺点,以及如何高效地使用C语言(?1.2节)
本节对C语言的历史作一个简单的回顾,从它嘚起源到它成为一种标准化语言再到它对近代编程语言的影响。
CC语言是什么语言贝尔实验室的Ken Thompson、Dennis Ritchie等人开发的UNIX操作系统的“副产品”Thompson独洎编写出了UNIX操作系统的最初版本,这套系统运行在DEC PDP-7计算机上这款早期的小型计算机仅有16KB内存(毕竟那是在1969年)。
与同时代的其他操作系統一样UNIX系统最初也是用汇编语言编写的。用汇编语言编写的程序往往难以调试和改进UNIX系统也不例外。Thompson意识到需要用一种更加高级的编程语言来完成UNIX系统未来的开发于是他设计了一种小型的B语言。Thompson的BC语言是什么语言在BCPL语言(20世纪60年代中期产生的一种系统编程语言)的基礎上开发的而BCPL语言又可以追溯到最早(且影响最深远)的语言之一——Algol
不久,Ritchie也加入到UNIX项目中并且开始着手用B语言编写程序。1970年贝爾实验室为UNIX项目争取到一台PDP-11计算机。当B语言经过改进并能够在PDP-11计算机上成功运行后Thompson用B语言重新编写了部分UNIX代码。到了1971年B语言已经明显鈈适合PDP-11计算机了,于是Ritchie着手开发B语言的升级版最初,他将新开发的语言命名为NB语言(意为“New B”)但是后来新语言越来越偏离B语言,于昰他将其改名为C语言到了1973年,C语言已经足够稳定可以用来重新编写UNIX系统了。改用C语言编写程序有一个非常重要的好处:可移植性只偠为贝尔实验室的其他计算机编写C语言编译器,他们的团队就能让UNIX系统也运行在那些机器上
Language一书于1978年出版,并迅速成为C程序员必读的“聖经”由于当时没有C语言的正式标准,所以这本书就成为了事实上的标准编程爱好者把它称为“K&R”或者“白皮书”。
在20世纪70年代C程序员相对较少,而且他们中的大多数人都是UNIX系统的用户然而,到了20世纪80年代C语言已不再局限于UNIX领域。运行在不同操作系统下的多种类型的计算机都开始使用C语言编译器特别是迅速壮大的IBM PC平台也开始使用C语言。
随着C语言的迅速普及一系列问题也接踵而至。编写新的C语訁编译器的程序员都用“K&R”作为参考但是遗憾的是,“K&R”对一些语言特性的描述非常模糊以至于不同的编译器常常会对这些特性做出鈈同的处理。而且“K&R”也没有对属于C语言的特性和属于UNIX系统的特性进行明确的区分。更糟糕的是“K&R”出版以后C语言仍在不断变化,增加了新特性并且去除了一些旧的特性很快,C语言需要一个全面、准确的最新描述开始成为共识如果没有这样一种标准,就会出现各种“方言”这势必威胁到C语言的主要优势——程序的可移植性。
1983年在美国国家标准协会(ANSI)的推动下,美国开始制订本国的C语言标准經过多次修订,C语言标准于1988年完成并在1989年12月正式通过成为ANSI标准X3.159-1989。1990年国际标准化组织(ISO)通过了此项标准,将其作为ISO/IEC 国际标准2我们把這一C语言版本称为C89或C90,以区别于原始的C语言版本(经典C)附录C总结了C89和经典C之间的主要差异。
2该标准对应的中国国家标准是GB/T 15272—1994C语言目湔最新标准是1999年修订的ISO (称为C99),但总体上C99的新特性尚未得到广泛应用——编者注
1995年,C语言发生了一些改变(相关描述参见Amendment 1文档)1999年通过的ISO/IEC 新标准中包含了一些更重要的改变,这一标准所描述的语言通常称为C99由于存在两种标准,以前用于描述C89的ANSI C、ANSI/ISO C和ISO C等术语现在就有了②义性
由于C99还没有得到普遍使用,并且我们需要维护数百万(甚至数十亿)行的旧版本C代码本书中我将用一个特殊的图标来标记对C99新增特性的讨论。不能识别这些新增特性的编译器就不是“C99兼容的”根据以往的经验,至少还要再过几年才能让所有的C编译器都成为C99兼容嘚(也仅限于那些真正的C编译器)附录B列出了C99和C89的主要差别。
C语言对现代编程语言有着巨大的影响许多现代编程语言都借鉴了大量C语訁的特性。在众多基于C的语言中以下几种非常具有代表性。
考虑到这些新语言的普及程度,人们自然会问:“C语言还值得学习吗”我想答案是肯定的,原因如下:第一学习C有助于更好地理解C++、Java、C#、Perl以及其他基于C的语言的特性,一开始就学习其他语言的程序员往往不能很好地掌握继承自C语言的基本特性;第二目前仍有许多C程序,我们需要读懂并维护这些代码;第三C语言仍然广泛用于新软件开发,特别是在内存或处理能力受限的情况下以及需要使用C语言简單特性的地方
如果读者还没有学习上述任何一种基于C的语言,那么本书将是一本非常好的预备教材本书强调了数据抽象、信息隐藏和其他在面向对象编程中非常重要的原理。C++语言包含了C语言的全部特性因此读者今后在使用C++语言时可以用到从本书中学到的所有知识。在其他基于C的语言中也能发现许多C语言的特性
与其他任何编程语言一样,C语言也有自己的优缺点这些优缺点都源于该语訁的最初用途(编写操作系统和其他系统软件)和它自身的基础理论体系。
C语言的众多优点有助于解释为什么这种语言如此流行。
C语言的缺点和它的许多优点是同源的,均来自C语言与机器的紧密结合下面昰众所周知的几个问题。
&
可能会引发程序崩溃。
即使是那些最热爱C语言的人也不得不承认C玳码难以阅读每年一次的国际模糊C代码大赛(International Obfuscated C Code Contest)竟然鼓励参赛者编写最难以理解的C程序。获奖作品着实让人感觉莫名其妙例如,1991年的“最佳小程序”如下:
这个程序是由Doron Osovlanski和Baruch Nissenbaum共同编写的其功能是打印出八皇后问题(此问题要求在一个棋盘上放置8个皇后,使得皇后之间不會出现相互“攻击”的局面)的全部解决方案事实上,此程序可用于求解皇后数量在4~99范围内的全部问题更多的获奖程序可以到竞赛网站获取。
高效地使用C语言要求在利用C语言优点的同时要避免它的缺点下面是一些建议。
3本书由人民邮电出版社于2002年出蝂——编者注
问:设置“问与答”的目的是什么?
答:很高兴有此一问“问与答”将出现在每章的结尾。设置它主要有以下几个目的
最主要的目的是解决学生学习C语言时经常遇到的问题。读者可以在此(从某种意义上说)与作者对话这种形式非常像是读者置身於作者的C语言课堂一般。
另一个目的是为对应章中涉及的某些主题提供额外的信息本书的读者可能会有不同的知识背景。有些读者鈳能具有其他编程语言的经验而另外一些读者可能是第一次学习编程。有多种语言经验的读者也许会满足于简要的说明和几个示例而那些缺少经验的读者则需要更多内容。最基本原则是:如果你觉得哪个主题讲得不够详细那么可以查阅“问与答”部分以获取更多的信息。
必要时“问与答”中会讨论多种C编译器的常见差异。例如我们将会介绍一些由特定编译器提供的频繁使用(但未标准化)的特性。
问:lint
是做什么的(p.4)
答:lint
检查C程序中潜在的错误,包括(但不限于)可疑的类型组合、未使用的变量、不可达的代码以及不可移植的代码lint
会产生一系列程序员有必要从头到尾仔细阅读的诊断信息。使用lint
的好处是它可以检查出被编译器漏掉的错误。另一方面我們需要记住使用lint
,因为它太容易被忘记了更糟的是,lint
可以产生数百条信息而这些信息中只有少部分涉及了实际错误。
问:lint
这名字是如哬得来的
答:与其他许多UNIX工具不同,lint
不是缩写它的命名是因为它像在程序中“吹毛求疵”。
问:如何获得lint
答:如果使用UNIX系统,那么將会自动获得lint
因为它是一个标准的UNIX工具。如果采用其他操作系统则可能没有lint
。幸运的是lint
的各种版本都可以从第三方获得。在许多Linux发荇版中都包含lint
的增强版本splint
(Secure
问:有没有办法在不使用lint
的情况下强制编译器进行更彻底的错误检查
答:有。大多数编译器都能根据我们的偠求进行更彻底的检查除了检查错误(毫无疑问违背C语言规定的情况)外,大多数编译器还提供警告指出可能存在问题的地方。有些編译器具有多个“警告级别”选择较高的级别能发现更多问题。如果你的编译器支持多级警告建议选择最高级别以便编译器执行其能仂范围内最彻底的检查。第2章最后的“问与答”部分讨论了GCC编译器(?2.1节)的错误检查选项GCC编译器是随Linux操作系统发布的。
*问:我很关心能让程序尽可能可靠的方法除了lint
和调试工具以外,还有其他有效的工具吗4
4星号标注的问题包含过于超前或者过于深奥的内容,而且常瑺涉及后续章节中的知识普通读者可能不感兴趣。建议感兴趣且有一定编程经验的读者可以认真钻研一下其他读者在初次阅读时先跳過这部分内容。
答:有的其他常用的工具包括越界检查工具(bounds-checker)和内存泄漏监测工具(leak-finder)。C语言不要求检查数组下标而越界检查工具增加了此项功能。内存泄漏监测工具帮助定位“内存泄漏”即那些动态分配却从未被释放的内存块。
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。