最初,并没有官方的 C 库。后来,基于 UNIX 的 C 实现成为了标准。ANSI C 委员会主要以这个标准为基础,开发了一个官方的标准库。在意识到 C 语言的应用范围不断扩大后,该委员会重新定义了这个库,使之可以应用于其他系统。
我们讨论过一些标准库中的 I/O 函数、字符函数和字符串函数。本章将介绍更多函数。不过,首先要学习如何使用库。
访问 C 库
如何访问C库取决于实现,因此你要了解当前系统的一般情况。
首先,可以在多个不同的位置找到库函数。例如,getchar() 函数通常作为宏定义在 stdio.h 头文件中,而 strlen() 通常在库文件中。
其次,不同的系统搜索这些函数的方法不同。下面介绍3种可能的方法:
自动访问 。在一些系统中,只需编译程序,就可使用一些常用的库函数。记住,在使用函数之前必须先声明函数的类型,通过包含合适的头文件即可完成。在描述库函数的用户手册中,会指出使用某函数时应包含哪个头文件。但是在一些旧系统上,可能必须自己输入函数声明。再次提醒读者,用户手册中指明了函数类型。过去,不同的实现使用的头文件名不同。ANSI C 标准把库函数分为多个系列,每个系列的函数原型都放在一个特定的头文件中。文件包含 。如果函数被定义为宏,那么可以通过 #include 指令包含定义宏函数的文件。通常,类似的宏都放在合适名称的头文件中。例如,许多系统(包括所有的 ANSI C 系统)都有 ctype.h 文件,该文件中包含了一些确定字符性质(如大写、数字等)的宏。库包含 。在编译或链接程序的某些阶段,可能需要指定库选项。即使在自动检查标准库的系统中,也会有不常用的函数库。必须通过编译时选项显式指定这些库。注意,这个过程与包含头文件不同。头文件提供函数声明或原型,而库选项告诉系统到哪里查找函数代码。虽然这里无法涉及所有系统的细节,但是可以提醒读者应该注意什么。
库描述
可以在多个地方找到函数文档。你所使用的系统可能有在线手册,集成开发环境通常都有在线帮助。C 实现的供应商可能提供描述库函数的纸质版用户手册,或者把这些材料放在 CD-ROM 中或网上。有些出版社也出版 C 库函数的参考手册。这些材料中,有些是一般材料,有些则是针对特定实现的。
阅读文档的关键是看懂函数头。许多内容随时间变化而变化。下面是旧的 UNIX 文档中,关于 fread() 的描述:
#include <stdio.h> fread(ptr, sizeof(*ptr), nitems, stream) FILE *stream; 复制代码 首先,给出了应该包含的文件,但是没有给出 fread()、ptr、sizeof(*ptr) 或 nitems 的类型。过去,默认类型都是 int,但是从描述中可以看出 ptr 是一个指针(在早期的 C 中,指针被作为整数处理)。参数 stream 声明为指向 FILE 的指针。上面的函数声明中的第 2 个参数看上去像是 sizeof 运算符,而实际上这个参数的值应该是 ptr 所指向对象的大小。虽然用 sizeof 作为参数没什么问题,但是用 int 类型的值作为参数更符合语法。
后来,上面的描述变成了:
#include <stdio.h> int fread(ptr, size, nitems, stream;) char *ptr; int size, nitems; FILE *stream; 复制代码 现在,所有的类型都显式说明,ptr 作为指向 char 的指针。ANSI C90 标准提供了下面的描述:
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 复制代码 首先,使用了新的函数原型格式。其次,改变了一些类型。size_t 类型被定义为 sizeof 运算符的返回值类型 —— 无符号整数类型,通常是 unsigned int 或 unsigned long。stddef.h 文件中包含了 size_t 类型的 typedef 或 #define 定义。 其他文件(包括stdio.h)通过包含 stddef.h 来包含这个定义。许多函数(包括 fread())的实际参数中都要使用 sizeof 运算符,形式参数的 size_t 类型中正好匹配这种常见的情况。
另外,ANSI C 把指向 void 的指针作为一种通用指针,用于指针指向不同类型的情况。例如,fread() 的第1个参数可能是指向一个 double 类型数组的指针,也可能是指向其他类型结构的指针。如果假设实际参数是一个指向内含20个 double 类型元素数组的指针,且形式参数是指向 void 的指针,那么编译器会选用合适的类型,不会出现类型冲突的问题。
C99/C11标准在以上的描述中加入了新的关键字 restric:
#include <stdio.h> size_t fread(void * restrict ptr, size_t size,size_t nmemb, FILE * restrict stream); 复制代码
restric 关键字只用于指针,表示该指针是唯一指向这个对象的指针。