11.2.2 C语言标准库(1)
在本章节里,我们将介绍C语言标准库的基本函数集合,并对其中一些特殊函数进行详细的介绍。ANSI C的标准库由24个C头文件组成。与许多其他语言(如Java)的标准库不同,C语言的标准库非常轻量,它仅仅包含了数学函数、字符/字符串处理,I/O等基本方面,例如:
标准输入输出(stdio.h)。
文件操作(stdio.h)。
字符操作(ctype.h)。
字符串操作(string.h)。
数学函数(math.h)。
资源管理(stdlib.h)。
格式转换(stdlib.h)。
时间/日期(time.h)。
断言(assert.h)。
各种类型上的常数(limits.h & float.h)。
除此之外,C语言标准库还有一些特殊的库,用于执行一些特殊的操作,例如:
变长参数(stdarg.h)。
非局部跳转(setjmp.h)。
相信常见的C语言函数读者们都已经非常熟悉,因此这里就不再一一介绍,接下来让我们看看两组特殊函数的细节。
1. 变长参数
变长参数是C语言的特殊参数形式,例如如下函数声明:
int printf(const char* format, ...); |
va_list ap; |
va_start(ap, lastarg); |
type next = va_arg(ap, type); |
int sum(unsigned num, ...); |
其语义如下:
第一个参数传递一个整数num,紧接着后面会传递num个整数,返回num个整数的和。
当我们调用:
int n = sum(3, 16, 38, 53); |
|
| 图11-7 函数参数在栈上分布 |
int sum(unsigned num, ...) |
在这里我们可以观察到两个事实:
(1)sum函数获取参数的量仅取决于num参数的值,因此,如果num参数的值不等于实际传递的不定参数的数量,那么sum函数可能取到错误的或不足的参数。
(2)cdecl调用惯例保证了参数的正确清除。我们知道有些调用惯例(如stdcall)是由被调用方负责清除堆栈的参数,然而,被调用方在这里其实根本不知道有多少参数被传递进来,所以没有办法清除堆栈。而cdecl恰好是调用方负责清除堆栈,因此没有这个问题。
printf的不定参数比sum要复杂得多,因为printf的参数不仅数量不定,而且类型也不定。所以printf需要在格式字符串中注明参数的类型,例如用%d表明是一个整数。printf里的格式字符串如果将类型描述错误,因为不同参数的大小不同,不仅可能导致这个参数的输出错误,还有可能导致其后的一系列参数错误。
【小实验】
printf的狂乱输出 int main() |
0.000000 97 |
| 回书目 上一节 下一节 |
