前言
C语言接口与实现:创建可重用软件的技术
如今的程序员忙于应付大量关于API(Application Programming Interface)的信息。但是,大多数程序员都会在其所写的几乎每一个应用程序中使用API并实现API的库,只有少数程序员会创建或发布新的能广泛应用的API。事实上,程序员似乎更喜欢使用自己搞的东西,而不愿意查找能满足他们要求的程序库,这或许是因为写特定应用程序的代码要比设计可广泛使用的API容易。
不好意思,我也未能免俗:lcc(我和Chris Fraser为ANSI/ISO C编写的编译器)就是从头开始编写的API。(在A Retargetable C Compiler: Design and Implementation一书中有关于lcc的介绍。)编译器是这样一类应用程序:可以使用标准接口,并且能够创建在其他地方也可以使用的接口。这类程序还有内存管理、字符串和符号表以及链表操作等。但是lcc仅使用了很少的标准C库函数的例程,并且它的代码几乎都无法直接应用到其他应用程序中。
本书提倡的是一种基于接口及其实现的设计方法,并且通过对24个接口及其实现的描述详细演示了该方法。这些接口涉及很多计算机领域的知识,包括数据结构、算法、字符串处理和并发程序。这些实现并不是简单的玩具,而是为在产品级代码中使用而设计的。实现的代码是可免费提供的。
C编程语言基本不支持基于接口的设计方法,而C++和Modula-3这样的面向对象的语言则鼓励将接口与实现分离。基于接口的设计跟具体的语言无关,但是它要求程序员对像C一样的语言有更强的驾驭能力和更高的警惕性,因为这类语言很容易破坏带有隐含实现信息的接口,反之亦然。
然而,一旦掌握了基于接口的设计方法,就能够在服务于众多应用程序的通用接口基础上建立应用程序,从而加快开发速度。在一些C++环境中的基础类库就体现了这种效果。增加对现有软件(接口实现库)的重用,能够降低初始开发成本,同时还能降低维护成本,因为应用程序的更多部分都建立在通用接口的实现之上,而这些实现无不经过了良好的测试。
本书中的24个接口引自几本参考书,并且针对本书特别做了修正。一些数据结构(抽象数据类型)中的接口源于lcc代码和20世纪70年代末到80年代初所做的Icon编程语言的实现代码(参见R. E. Griswold和M. T. Griswold所著的The Icon Programming Language)。其他的接口来自另外一些程序员的著作,我们将会在每一章的“扩展阅读”部分给出详细信息。
书中提供的一些接口是针对数据结构的,但本书不是介绍数据结构的,本书的侧重点在算法工程(包装数据结构以供应用程序使用),而不在数据结构算法本身。然而,接口设计的好坏总是取决于数据结构和算法是否合适,因此,本书可算是传统数据结构和算法教材(如Robert Sedgewick所著的Algorithms in C)的有益补充。
大多数章节会只介绍一个接口及其实现,少数章节还会描述与其相关的接口。每一章的“接口”部分将会单独给出一个明确而详细的接口描述。对于兴趣仅在于接口的程序员来说,这些内容就相当于一本参考手册。少数章节还会包含“例子”部分,会说明在一个简单的应用程序中接口的用法。
每章的“实现”部分将会详细地介绍本章接口的实现代码。有些例子会给出一个接口的多种实现方法,以展示基于接口设计的优点。这些内容对于修改或扩展一个接口或是设计一个相关的接口将大有裨益。许多练习题会进一步探究一些其他可行的设计与实现的方法。如果仅是为了理解如何使用接口,可以不用阅读“实现”一节。
接口、示例和实现都以文学(literate)程序的方式给出,换句话说,源代码及其解释是按照最适合理解代码的顺序交织出现的。代码可以自动地从本书的文本文件中抽取,并按C语言所规定的顺序组合起来。其他也用文学程序讲解C语言的图书有A Retargetable C Compiler和D. E. Knuth写的The Stanford GraphBase: A Platform for Combinatorial Computing。
目 录
第1章 引言
1.1 文学程序
1.2 程序设计风格
1.3 效率
1.4 扩展阅读
1.5 习题
第2章 接口与实现
2.1 接口
2.2 实现
2.3 抽象数据类型
2.4 客户程序的职责
2.5 效率
2.6 扩展阅读
2.7 习题
第3章 原子
第4章 异常与断言
第5章 内存管理
第6章 再谈内存管理
第7章 链表
第8章 表
第9章 集合
第10章 动态数组
第11章 序列
第12章 环
第13章 位向量
第14章 格式化
第15章 低级字符串
第16章 高级字符串
第17章 扩展精度算术
第18章 任意精度算术
第19章 多精度算术
第20章 线程
附录A 接口摘要
参考书目
欢迎来到异步社区!