The C Programming Language(2nd Ed) Introduction 翻译

说明:

1.       本人非专业翻译人员,信达雅三种境界,可以达到“信”就很庆幸了。

2.       翻译本文只是为了在学习其中内容的同时提高英语水平,仅供学习交流之用。

3.       希望本文能为他人提供一些帮助,尤其是那些和我一样吃力地啃英文书籍和文档的朋友。

4.       译文中若有任何错误和不当之处,欢迎批评指正。

 

原书书名:The C Programming Language (Second Edition)

原书作者:Brian W. Kernighan; Dennis M. Ritchie

原书简介:C语言的创始人所写的C语言书籍,据说很薄的一本书就把C语言写透了。不过似乎不完全是针对初学者的,但内容写的深入浅出,初学者仍可以看的。我最开始学C语言用的书就是上课的教材,现在连书名都记不太清楚了。后来为了提高水平,又看了谭浩强的书,的确很好,只是看后觉得收获不大,可能是因为跟第一本书一样,都是入门书籍吧。最近选择了这本英文原著,希望可以从这本书中有所收获,目前正在拜读中……

 

译文章节:Introduction

 

引言

C语言是一种通用的编程语言。由于UNIX系统本身以及在其上运行的大多数程序都是用C语言编写的,所以C语言和UNIX系统有十分紧密的联系。不过,尽管C语言常用于编写编译器和操作系统,并因此被称为“系统编程语言”,但它绝不仅仅局限于任何一个操作系统或者硬件平台。在许多领域中的核心程序都是用C语言编写的。

许多C语言中的重要概念都源于Martin Richards开发的BCPL语言。而BCPL语言对C语言的影响,间接来自B语言。1970年,Ken ThompsonDEC 公司生产的PDP-7小型机上编写第一个UNIX系统时,用的就是B语言。

BCPLB都是无类型(typeless)的编程语言。相较而言,C语言提供了大量的数据类型。基本的数据类型包括字符型、整型和浮点型等。此外,还有一些基于指针(pointer)的派生数据类型,像数组、结构体和共用体。C语言的表达式由操作符和操作数构成。像赋值和调用函数等任何表达式都是C语言的语句。C语言的指针提供了独立于机器的地址运算。

C语言提供了用于结构化编程的基本控制流结构:声明分组,决策语句(if-else),多分支选择语句(switch),在每次循环开始时进行终止条件检测的循环语句(whilefor),在每次循环结束时进行终止条件检测的循环语句(do),以及跳出循环语句(break)。

C语言中,函数的返回值可以是基本数据类型,也可以是结构体、共用体或者指针。任何函数都可以进行递归调用。函数中的本地变量都会在函数结束时删除,并在每次函数被调用时自动重新创建。值得注意的是,虽然函数定义不能被嵌套,但变量却能够以块结构化的形式进行定义(此句字面翻译,不完全理解)。C程序的函数可以存在于不同的源文件中,并分别被编译。变量的作用域可以仅限于其所在的函数、单一的源文件或者整个程序。

C语言的预处理过程用于将程序代码中的宏替换为宏的具体内容,包含其他源文件以及进行条件编译。

C语言是一个相对“低级”的语言。这并不是一个贬义的说法,而仅仅意味着C语言可以处理一些大多数计算机可以处理的对象,即字符,数字和地址。针对这些对象的操作包括算数和逻辑运算,这也是真正的机器实现的操作。

C语言无法直接处理复合对象,例如字符串、集、表和数组等。虽然结构体可以作为一个单元被复制,但仍然无法对整个数组或字符串进行操作。除了用于函数的本地变量的静态定义和静态规范,C语言没有定义任何内存分配机制,像堆和垃圾回收等。C语言本身没有提供输入输出功能、读写语句和内建的文件处理方法。所有这些高级功能都只能由显式调用函数实现。实现这些功能的函数大多数都包含在合理的C标准集里。

同样,C语言只提供简单的单线程控制流:测试,循环,分组和子程序,并没有多程序处理,并行操作,同步处理和协同程序等功能。

尽管没有这些特征看起来像是一个严重的缺陷(你是说必须调用一个函数才能比较两个字符串?),但是保持编程语言在一个适度规模具有许多实际的好处。因为C语言的规模比较小,它可以在很小的篇幅里被描述并迅速学习。一个编程者可以合理的理解和确实地经常应用全部语言。

多年以来,C语言的定义就是《The C Programming Language》第一版的参考手册。但在1983年,美国国家标准协会建立了一个委员会,用于提供一个现代的、综合的C标准,并最终在1988年产生了ANSI标准,即ANSI C。现在的编译器仍然支持ANSI标准的许多特征。

这个标准是基于最原始的参考手册的。在语言上有相对较少的改变。这个标准的目的之一就是保证大多数已经存在的程序仍然有效,如果程序不能运行,也要求编译器能给出新行为的警告信息。

对于大多数的编程者,ANSI标准最重要的改变是声明和定义函数的语法。函数的声明部分可以包含函数参数的描述,函数定义的语法会自动匹配这些描述。这个额外的信息使得编译器十分容易检测由参数不匹配所引起的错误。根据我们的经验,这是一个十分有用的功能。

当然,在ANSI标准中还有一些其他的小改变。结构体赋值和枚举都被广泛使用,已经正式成为C语言的一部分。浮点运算能够以单精度实现。算数运算的性能有所提高,尤其是针对无符号类型的。预处理过程也更加缜密了。大多数这样的改变只会对编程者有很小的影响。

ANSI标准的另一个显著贡献是定义了伴随C语言的函数库。这个函数库指定了访问操作系统(例如,读写文件),格式化输入输出,内存分配,字符串处理操作等等。通过包含标准头文件,可以提供对函数和数据声明的统一的访问方式。程序通过这些库函数与主机系统进行的交互一定是具有兼容性的操作。大多数库函数是以UNIX系统的“标准IO库”为蓝本的。这个UNIX系统的库自第一版以后,便迅速被广泛应用于其他系统。同样,大多数编程者不会对这一点感受到很大改变。

由于C语言的数据类型和控制结构可以直接被大多数计算机支持,其需要实现自包含程序的运行库就十分小。标准库函数只能被显式的调用,所以不需要的函数都可以避免被包含进去。除了被隐藏的操作系统细节,标准库的大部分函数可以用C编写,并且具有可移植性。

尽管C语言可以和许多计算机的硬件相匹配,但它是独立于任何计算机结构的。不用太关心这些硬件差异,就可以编写出可移植的程序,使得这些程序可以不经修改就在许多不同的硬件上运行。ANSI标准使得可移植问题变得十分明确,只要指定一系列描述程序运行的机器的特征的常量即可。

C语言不是一种“强类型”的语言,但随着它的发展,它的类型检查机制已经十分强大。原始定义的C语言虽然不赞成但允许指针和整数的转换,现在已经不再允许。ANSI标准要求合适的声明和显示转换,这些早已在优秀的编译器中强制要求了。新的函数声明方式也是这个发展方向的一部分。编译器会对大多数类型错误提出警告,并且不会对不相容的数据类型进行转换。尽管如此,C语言保留了其基本的哲学思想,只要编程者明确表达了自己的意图,他们永远知道自己在做什么。

就像其他语言一样,C语言有其自身的缺陷。像一些运算符具有错误的优先权,一些语法可以有更好的替代方式等。但无论如何,C语言已经被证明是一种十分高效和表达能力强,而且具有广泛编程应用的语言。

本书安排如下。第1章是关于C语言核心部分的教程。目的在于使读者尽快开始使用C语言,因为我们十分相信,学习一种新的编程语言的最好方法就是用这种语言去编程。该教程假设读者已经具有对编程基本要素的工作知识。也就是说,在这个教程里没有关于计算机和汇编的解释,也没有说明像n=n+1这种表达式的含义。尽管我们已经尝试了各种可能去展示有用的编程技巧,但由于本书的目的不是作为专门讲解数据结构和算法的参考,当面对两者之间的选择时,我们更专注于语言本身。

2章到第6章更详细地讨论了C语言的方方面面,而且虽然其重点仍是完整程序的例子,而非孤立的程序段,但在语言上比第1章更正式。第2章讲解了基本的数据类型、运算符和表达式。第3章讲解控制流语句:if-else, switch, while, for等。第4章介绍函数和程序结构——外部变量,作用域规则,多源文件等,同样也讨论了预处理。第5章讨论指针和地址运算。第6章介绍了结构体和共用体。

7章介绍标准库的内容,该库提供了操作系统的通用接口。标准库有ANSI标准定义,并意图支持所有支持C语言的机器,以使所有利用标准库进行输入输出或其他操作系统交互行为的程序可以不做改变的移植到其他系统。

8章介绍了C程序和UNIX操作系统的接口,专注于输入输出,文件系统和内存分配。虽然本章中的一些部分专门针对UNIX系统的,使用其他系统的编程者仍然能从中有所收获,包括一些对于某一版本标准库的实现过程的见解和可移植性的建议。

附录A是一个语言参考手册。C语言语法和语义的官方声明就是ANS标准本身。但是,这个标准的文档主要是面向编译器的编写者的。这个参考手册没有使用严格的表述风格,而是更加简明扼要地表达了语言的定义。附录B是一个标准库的总结,同样是面向使用者,而非实现者的。附录C是对ANSI C 标准与原始C语言的变化的简短总结。但是,如果有疑问,该标准和任何人自己的编译器保留对语言的最终解释权。