第 25 章 C 标准库
在前面的各章中我们已经见过 C 标准库的一些用法,总结如下:
- 我们最常用的是包含
stdio.h,使用其中声明的printf函数,这个函数在libc中实现,程序在运行时要动态链接libc共享库。 - 在第 1 节“数学函数”中用到了
math.h中声明的sin和log函数,使用这些函数需要动态链接libm共享库。 - 在第 2 节“数组应用实例:统计随机数”中用到了
stdlib.h中声明的rand函数,还提到了这个头文件中定义的RAND_MAX常量,在例 8.5“剪刀石头布”中用到了stdlib.h中声明的srand函数和time.h中声明的time函数。使用这些函数需要动态链接libc共享库。 - 在第 2 节“
main函数和启动例程”中用到了stdlib.h中声明的exit函数,使用这个函数需要动态链接libc共享库。 - 在第 6 节“折半查找”中用到了
assert.h中定义的assert宏,在第 4 节“其它预处理特性”中我们看到了这个宏的一种实现,它的实现需要调用stdio.h和stdlib.h中声明的函数,所以使用这个宏也需要动态链接libc共享库。 - 在第 2.4 节“sizeof 运算符与 typedef 类型声明”中提到了
size_t类型在stddef.h中定义,在第 1 节“指针的基本概念”中提到了NULL指针也在stddef.h中定义。 - 在第 1 节“本章的预备知识”中介绍了
stdlib.h中声明的malloc和free函数以及string.h中声明的strcpy和strncpy函数,使用这些函数需要动态链接libc共享库。 - 在第 6 节“可变参数”中介绍了
stdarg.h中定义的va_list类型和va_arg、va_start、va_end等宏定义,并给出了一种实现,这些宏定义的实现并没有调用库函数,所以不依赖于某个共享库,这一点和assert不同。
总结一下,Linux 平台提供的 C 标准库包括:
- 一组头文件,定义了很多类型和宏,声明了很多库函数。这些头文件放在哪些目录下取决于不同的编译器,在我的系统上,
stdarg.h和stddef.h位于/usr/lib/gcc/i486-linux-gnu/4.3.2/include目录下,stdio.h、stdlib.h、time.h、math.h、assert.h位于/usr/include目录下。C99 标准定义的头文件有 24 个,本书只介绍其中最基本、最常用的几个。 - 一组库文件,提供了库函数的实现。大多数库函数在
libc共享库中,有些库函数在另外的共享库中,例如数学函数在libm中。在第 4 节“共享库”讲过,通常libc共享库是/lib/libc.so.6,而我的系统启用了 hwcap 机制,libc共享库是/lib/tls/i686/cmov/libc.so.6。
本章介绍另外一些最基本和最常用的库函数(包括一些不属于 C 标准但在 UNIX 平台上很常用的函数),写这一章是为了介绍字符串操作和文件操作的基本概念,而不是为了写一本 C 标准库函数的参考手册,Man Page 已经是一本很好的手册了,读者学完这一章之后在开发时应该查阅 Man Page,而不是把我这一章当参考手册来翻,所以本章不会面面俱到介绍所有的库函数,对于本章讲到的函数有些也不会讲得很细,因为我假定读者经过上一章的学习再结合我讲过的基本概念已经能看懂相关的 Man Page 了。很多技术书的作者给自己的书太多定位,既想写成一本入门教程,又想写成一本参考手册,我觉得这样不好,读者过于依赖技术书就失去了看真正的手册的能力。