目录
C标准主要由两部分组成,一部分描述C的语法,一部分描述C标准库。换句话说,要在一个平台上支持C语言,不仅要实现C编译器,还要实现C标准库,这样的实现才算符合C标准。不符合C标准的实现也是存在的,例如有些单片机的C语言开发工具中只有C编译器而没有完整的C标准库。
在前面的各章中我们已经见过C标准库的一些用法,总结如下:
我们最常用的是包含stdio.h
,使用其中声明的printf
函数,这个函数在libc
中实现,程序在运行时要动态链接libc
共享库。
在“数学函数”一节中用到了math.h
中声明的sin
和log
函数,使用这些函数需要动态链接libm
共享库。
在“数组应用实例:统计随机数”一节中用到了stdlib.h
中声明的rand
函数,还提到了这个头文件中定义的RAND_MAX
常量,在例 8.3 “剪刀石头布”中用到了stdlib.h
中声明的srand
函数和time.h
中声明的time
函数。使用这些函数需要动态链接libc
共享库。
在“main
函数和启动例程”一节中用到了stdlib.h
中声明的exit
函数,使用这个函数需要动态链接libc
共享库。
在“折半查找”一节中用到了assert.h
中定义的assert
宏,在“其它预处理特性”一节中我们看到了这个宏的一种实现,它的实现需要调用stdio.h
和stdlib.h
中声明的函数,所以使用这个宏也需要动态链接libc
共享库。
在“sizeof运算符与typedef类型声明”一节中提到了size_t
类型在stddef.h
中定义,在“指针的基本操作”一节中提到了NULL
指针也在stddef.h
中定义。
在“本章的预备知识”一节中介绍了stdlib.h
中声明的malloc
和free
函数以及string.h
中声明的strcpy
和strncpy
函数,使用这些函数需要动态链接libc
共享库。
在“可变参数”一节中介绍了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
中。在“共享库”一节讲过,通常libc
共享库是/lib/libc.so.6
,而我的系统启用了hwcap机制,libc
共享库是/lib/tls/i686/cmov/libc.so.6
。
本章介绍另外一些最基本和最常用的库函数(包括一些不属于C标准但在UNIX平台上很常用的函数),写这一章是为了介绍字符串操作和文件操作的基本概念,而不是为了写一本C标准库函数的参考手册,Man Page已经是一本很好的手册了,读者学完这一章之后在开发时应该查阅Man Page,而不是把我这一章当参考手册来翻,所以本章不会面面俱到介绍所有的库函数,对于本章讲到的函数有些也不会讲得很细,因为我假定读者经过上一章的学习再结合我讲过的基本概念已经能看懂相关的Man Page了。很多技术书的作者给自己的书太多定位,既想写成一本入门教程,又想写成一本参考手册,我觉得这样不好,读者过于依赖技术书就失去了看真正的手册的能力。