C标准库
本附录为ANSI标准中定义的库的概要。标准库不是C语言本身的部分,但是支持标准C的环境将会提供该库中的函数说明、类型以及宏定义。我们这里没有讨论某些用途有限的函数以及某些可以简单地从其他函数合成的函数,我们也没有讨论多字节字符,同时也没有讨论程序局部环境问题,也就是说忽略了那些依赖于当地语言、国籍或文化的性质。
标准库中的各个函数、类型以及宏分别在以下标准头文件中说明:
<assert.h> <float.h> <math.h> <stdarg.h> <stdlib.h>
<ctype.h> <limits.h> <setjmp.h> <stddef.h> <string.h>
<errno.h> <locale.h> <signal.h> <stdio.h> <time.h>
我们可以用以下方式访问头文件:
#include <头文件>
头文件可以被多次以任意顺序包含。头文件必须被包含在外部声明和外部定义之外,在使用头文件的任何声明之前都必须先包含它。一个头文件不一定是一个源文件。以一个下划线开头的外部标识符保留给标准库使用,其他所有以一个下划线和一个大写字母开头的标识符和以两个下划线开头的标识符也都被保留给标准库使用。
B.1 输入与输出:<stdio.h>
在<stdio.h>头文件中所定义的用于输入和输出的函数、类型以及宏的数目将近占 整个标准库的三分之一。
流是磁盘或其他外围设备中存储的数据的源点或终点。尽管在一些系统中(如在 著名的UNIX系统中),文本流和二进制流是没有差别的,但是标准库中还是提供了这两种流。文本流是由文本行组成的序列,每一行有0个或多个字符并以'\n'结尾。在某些环境中也许需要把文本流转换成其他表示形式(例如把'\n'映射成回车符和换行符)或从其他表示形式转换过来。二进制流是未经处理的字节组成的序列,这些字节记录着内部数据,具有如下性质:如果在同一系统中把写出的二进制流再读入进来,读入的和写出的内容是完全相同的。通过打开一个流可以将该流与一个文件或设备关联起来,这一关联可以通过关闭流而终止。打开一个文件将返回一个指向FILE 类型对象的指针,该指针中记录有用于控制该流的所有必要的信息。在不会引起歧义性的情况下,我们在下文中将不再区分“文件指针”和“流”。
在程序开始执行时,stdin、stdout和stderr这三个流已经被打开。
B.1.1 文件操作
下列函数用于处理与文件有关的操作。其中size_t 类型是由运算符sizeof产生的无符号整类型。
FILE *fopen(const char *FILE name, const char *mode)
fopen函数用于打开以FILE name所指内容为名字的文件,返回与之相关联的流。如果打开操作失败,那么返回NULL。
访问方式mode的合法值如下:
"r" 打开文本文件用于读。
"w" 创建文本文件用于写,并删除已存在的内容(如果有的话)。
"a" 添加;打开或创建文本文件用于在文件末尾写。
"r+" 打开文本文件用于更新(即读和写)。
"w+" 创建文本文件用于更新,并删除已存在的内容(如果有的话)。
"a+" 添加;打开或创建文本文件用于更新和在文件末尾写。
后三种方式允许对同一文件进行读和写。在读和写的交替过程中,必须调用fflush函数或文件定位函数。如果方式值在上述字符之后再加上"b",如"rb"或"w+b"等,那么表示文件是二进制文件。文件名FILE name长度的最大值为FILE NAME_MAX个字符。一次最多可打开FOPEN_MAX个文件。
FILE *freopen(const char *FILE name, const char *mode, FILE *stream)
freopen函数用于以参数mode指定的方式打开参数FILE name指定的文件,并使该文件与参数stream指定的流相关联。它返回指向stream的指针;若出错则返回NULL。freopen函数一般用于stdin、stdout和stderr等标准流的重定向。
int fflush(FILE *stream)
对输出流,fflush函数用于将已写到缓冲区但尚未写出的全部数据都写到文件中。对输入流,其结果是未定义的。如果写的过程中发生错误则返回EOF,否则返回0。fflush(NULL)函数用于刷新所有的输出流。
int fclose(FILE *stream)
fclose函数用于刷新stream的全部未写出数据,丢弃任何未读的缓冲区内的输入数据并释放自动分配的缓冲区,最后关闭流。若出错则返回EOF,否则返回0。
int remove(const char *FILE name)
remove函数用于删除参数FILE name指定的文件,这样,随后进行的打开该文件的操作将失败。如果失败,则返回一个非0值。
int rename(const char *oldname, const char *newname)
rename函数用于改变文件的名字。如果操作失败,则返回一个非0值。
FILE *tmpFILE (void )
tmpFILE函数用于以方式wb+创建一个临时文件,该文件在被关闭或程序正常结束时被自动删除。该函数的返回值为一个流;如果创建文件失败,则返回NULL。
char *tmpnam(char s[L_tmpnam])
tmpnam(NULL)函数用于创建一个不同于现存文件名字的字符串,并返回一个指向一内部静态数组的指针。tmpnam(s)函数将所创建的字符串存储在数组s中,并将它返回作为函数值。s中至少要有L_tmpnam个字符的空间。tmpnam函数在每次被调用时均生成不同的名字。在程序的执行过程中,最多只能确保生成TMP_MAX个不同的名字。注意tmpnam函数只是用于创建一个名字,而不是创建一个文件。
int setvbuf(FILE *stream, char *buf, int mode, size_t size)
setvbuf函数用于控制stream所指定的流的缓冲区。在读、写以及其他任何操作之前必须调用此函数。当mode的值为_IOFBF时,将进行完全缓冲。当mode的值为_IOLBF时,对文本文件表示行缓冲;当mode的值为_IONBF时,表示不设置缓冲。如果变元buf的值不是NULL,则setvbuf函数将buf指向的区域作为指定流的缓冲区;否则就分配一个缓冲区。size决定缓冲区的大小。如果出错则setvbuf返回一个非0值。
void setbuf(FILE *stream, char *buf)
如果buf的值为NULL,那么stream所指定流的缓冲区将被关闭;否则setbuf函数等价于
(void) setvbuf(stream,buf,_IOFBF,BUFSIZ)。
B.1.2 格式化输出
printf类函数用于提供格式化的输出转换。
int fprintf(FILE *stream, const char *format, ...)
fprintf函数用于按照format说明的格式把变元表中变元的内容进行转换,并写入stream指向的流。返回值是实际写入的字符数。若出错则返回一个负值。
格式化字符串由两种类型的对象组成:普通字符(它们被拷贝到输出流)与转换规格说明(它们决定变元的转换和输出格式)。每个转换规格说明均以字符%开头,以转换字符结束。在“%”与转换字符这二者之间依次可以有以下转换字符:
· 标记(可以以任意顺序出现)用于修改变换说明:
- 指定被转换的变元在其字段内左对齐。
+ 指定在输出的数前面加上正负号。
空格 如果第一个字符不是正负号,那么在其前面附加一个空格。
0 对于数值转换,说明在输出长度小于字段宽时,加前导0。
# 指定其他输出形式。对于o格式,第一个数字必须为零。对于x或X格式,指定在输出的非0值前加0x或0X。对于e、E、f、g和G格式,指定输出总有一个小数点。对于g和G格式,指定输出值后面无意义的0将被保留。
· 一个指定最小字段宽的数。转换后的变元输出宽度至少要达到这个数值。如果变元的字符数小于此数值,那么在变元左边(或右边,按要求而定)添加前导字符。前导字符通常为空格,但是如果设置了0前导指示符,那么前导字符为0。
· 点号用于把字段宽和精度分开。
· 精度,对于字符串,说明输出字符的最大数目;对于e、E和f格式,说明输出的小数位数;对于g和G格式,说明输出的有效位数;对于整数,说明输出的最小位数(必要时可加前导0)。
· 长度修饰符h、l、L"h"表示对应的变元按short或unsigned short类型输出。"l"表示对应的变元按long 或unsigned long 类型输出。"L"表示对应的变元按long double类型输出。
在格式串中字段宽和精度二者或其中任何一个均可用*来指定,此时该值可通过转换下面的变元来求得,这些变元必须为int 类型。转换字符和它们的命令如表B-1所示。如果%后面的字符不是转换字符,那么该行为是未定义的。
表B-1 printf函数的转换字符
格式码 变元类型;转换效果
d,i int; 有符号十进制表示法
o int; 无符号八进制表示法(无前导0)
x,X int; 无符号十六进制表示法(无前导0X和0x),对0x用abcdef,对0X用ABCDEF
u int; 无符号十进制表示法
c int; 单个字符,转换为unsigned char 类型后
s char*; 输出字符串直到遇到'\0'或者已达到由精度指定的字符数
f double; 形如[-]mmm.ddd的十进制浮点数表示法,d的数目由精度确定。缺省精度为6位,精度为0时不输出小数点
e,E double; 形如[-]m.dddddde±xx或[-]m.ddddddE±xx的十进制表示法。d的数目由精度确定,缺省精度为6位。精度为0时不输出小数点
g,G double; 当指数值小于-4或大于等于精度时,采用%e或%E的格式;否则采用%f的格式。尾部的0与小数点不打印
p void*; 输出指针值(具体表示与实现有关)
n int*; 到目前为止以此格式调用printf输出的字符的数目将被写入到相应变元中。不进行变元转换
% 不转换; 输出符号%
int printf(const char *format, ...)
printf(...)函数等价于fprintf(stdout, ...)。
int sprintf(char *s, const char *format, ...)
sprintf函数与printf函数的功能基本相同,但输出到数组s中,并以'\0'结束。s必须足够大,以便能装下输出结果。该函数返回实际输出的字符数,不包括'\0'。
vprintf(const char *format, va_list arg)
vfprintf(FILE *stream, const char *format, va_list arg)
vsprintf(char *s, const char *format, va_list arg)
vprintf、vfprintf与vsprintf这几个函数与对应的printf函数等价,但变元表由arg代替。arg由宏va_start初始化,由va_arg调用。参见B.7节对<stgarg.h>头文件的讨论。
B.1.3 格式化输入
scanf类函数用于提供格式化输入转换。
int fscanf(FILE *stream, const char *format, ...)
fscanf函数用于在格式串format的控制下从流stream中读入字符,把转换后的值赋给后续各个变元,在此每一个变元都必须是一个指针。当格式串format结束时函数返回。如果到达文件的末尾或在变元被转换前出错,那么该函数返回EOF;否则返回实际被转换并赋值的输入项的数目。
格式字符串format通常包含有用于指导输入转换的转换规格说明。格式字符串中可以包含:
· 空格或制表符,它们将被忽略。
· 普通字符(“%”除外),与输入流中下一个非空白的字符相匹配。
· 转换规格说明,由一个%、一个赋值屏蔽字符*(任选)、一个用于指定最大字段宽的数(任选)、一个用于指定目标字段的字符(h、l或L)(任选)以及一个转换字符组成。
转换规格说明决定了输入字段的转换方式。通常把结果保存在由对应变元指向的变量中。然而,如果转换规格说明中包含有赋值屏蔽字符“*”,例如%*s,那么就跳过对应的输入字段,不进行赋值。输入字段是一个由非空白符组成的字符串,当遇到空白符或到达最大字段宽(如果有的话)时,对输入字段的读入结束。这意味着scanf函数可以跨越行的界限来读入其输入,因为换行符也是空白符(空白符包括空格、横向制表符、纵向制表符、换行符、回车符和换页符)。
转换字符说明了输入字段的解释含义,对应的变元必须是指针。合法的转换符如表B-2所示。
表B-2 scanf函数的转换字符
字符输入数据;变元类型
d 十进制整数;int*
i 整数;int*。该整数可以是以0开头的八进制数,也可以是以0x或0X开头的十六进制数
o 八进制整数(可以带或不带前导0);int*
u 无符号十进制整数;unsigned int*
x 十六进制整数(可以带或不带前导0x或0X);int*
c 字符;char *。按照字段宽的大小把读入的字符保存在指定的数组中,不加入字符'\0'。字段宽的缺省值为1。在这种情况下,不跳过空白符;如果要读入下一个非空白符,使用%1s
s 由非空白符组成的字符串(不包含引号);char*。该变元指针指向一个字符数组,该字符数组有足够空间来保存该字符串以及在末尾添加的'\0'
e、f、g 浮点数;float*。float浮点数的输入格式为:一个任选的正负号,一串可能包含小数点的数字和一个任选的指数字段。指数字段由字母e或E以及后跟的一个可能带正负号的整数组成
p 用printf("%p")函数调用输出的指针值;void*
n 将到目前为止此调用所读的字符数写入变元;int*。不读入输入字符。不增加转换项目计数
[...] 用方括号括起的字符集中的字符来匹配输入,以找到最长的非空字符串;char*。在末尾添加字符'\0'。格式[]...]表示字符集中包含字符]
[^...] 用不在方括号括起的字符集中的字符来匹配输入,以找到最长的非空字符串;char*。在末尾添加字符'\0'。格式[^]...]表示字符集中包含字符]
% 字面值%,不进行赋值
如果变元是指向short类型而不是int 类型的指针,那么在d、i、n、o、u和x这几个转换字符前可以加上字母h。如果变元是指向long 类型的指针,那么在这几个转换字符前可以加上字母l。如果变元是指向double类型而不是float类型的指针,那么在e、f和g这几个转换字符前可以加上字母l。如果变元是指向long double类型的指针,那么在e、f和g这几个转换字符前可以加上字母L。
int scanf(const char *format, ...)
scanf(...)函数与fscanf(stdin, ...)等价。
int sscanf(char *s, const *format, ...)
sscanf(s, ...)函数与scanf(...)等价,不同的是前者的输入字符来源于s。
B.1.4 字符输入输出函数
int fgetc(FILE *stream)
fgetc函数用于以unsigned char 类型返回stream流中的下一个字符(转换为int 类型)。如果到达文件的末尾或发生错误,则返回EOF。
char *fgets(char *s, int n, FILE *stream)
fgets函数用于读入最多n-1个字符到数组s中。当遇到换行符时,把换行符保留在数组s中,读入不再进行。数组s以'\0'结尾。fgets函数返回数组s,如果到达文件的末尾或发生错误,则返回NULL。
int fputc(int c, FILE *stream)
fputc函数用于把字符c(转换为unsigned char 类型)输出到流stream中。它返回所写的字符,若出错则返回EOF。
int fputs(const char *s, FILE *stream)
fputs函数用于把字符串s(不包含字符'\n')输出到流stream中;它返回一个非负值,若出错则返回EOF。
int getc(FILE *stream)
getc函数等价于fgetc,不同之处为:当getc函数被定义为宏时,它可能多次计算stream的值。
int getchar(void )
getchar函数等价于getc(stdin)。
char *gets(char *s)
gets函数用于把下一个字符串读入到数组s中,并把读入的换行符替换为字符'\0'。它返回数组s,如果到达文件的末尾或发生错误则返回NULL。
int putc(int c, FILE *stream)
putc函数等价于fputc,不同之处为:当putc函数被定义为宏时,它可能多次计算stream的值。
int putchar(int c)
putchar(c)函数等价于putc(c, stdout)。
int puts(const char *s)
puts函数用于把字符串s和一个换行符输出到stdout。如果发生错误,那么它返回EOF;否则返回一个非负值。
int ungetc(int c, FILE *stream)
ungetc用于把字符c(转换为unsigned char 类型)写回到流stream中,下次对该流进行读操作时,将返回该字符。对每个流只能写回一个字符,且此字符不能是EOF。ungetc函数返回被写回的字符;如果发生错误,那么它返回EOF。
B.1.5 直接输入输出函数
size_t fread(void *ptr, size_t size, size_t nobj, FILE *stream)
fread函数用于从输入流stream中读入最多nobj个长度为size的对象到ptr指向的数组中,并返回所读入的对象数,此返回值可能小于nobj。实际执行状态可用函数feof或ferror得到。
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *stream)
fwrite函数用于把ptr所指向的数组中nobj个长度为size的对象输出到流stream中,并返回被输出的对象数。如果发生错误,则返回一个小于nobj的值。
B.1.6 文件定位函数
int fseek(FILE *stream, long offset, int origin)
fseek函数用于给与stream流相关的文件定位,随后的读写操作将从新位置开始。对于二进制文件,此位置被定位在由origin开始的offset个字符处。origin的值可能为SEEK_SET(文件开始处)、SEEK_CUR(当前位置)或SEEK_END(文件结束处)。对于文本流,offset必须为0,或者是由函数ftell返回的值(此时origin的值必须是SEEK_SET)。fseek函数在出错时返回一个非0值。
long ftell(FILE *stream)
ftell函数用于返回与stream流相关的文件的当前位置。在出错时返回-1L。
void rewind(FILE *stream)
rewind(fp)函数等价于fseek(fp,0L,SEEK_SET)与clearerr(fp)这两个函数顺序执行的效果。
int fgetpos(FILE *stream, fpos_t*ptr)
fgetpos函数用于把stream流的当前位置记录在*ptr中,供随后的fsetpos函数调用时使用。若出错则返回一个非0值。
int fsetpos(FILE *stream, const fpos_t*ptr)
fsetpos函数用于将流stream的位置定位在ptr所指向的位置。*ptr的值是在函数fgetpos调用时记录下来的。若出错则返回一个非0值。
B.1.7 错误处理函数
当发生错误或到达文件末尾时,标准库中的许多函数将设置状态指示符。这些状态指示符可被显式地设置和测试。另外,(定义在<errno.h>中的)整数表达式errno可包含一个出错序号,该数将进一步给出最近一次出错的信息。
void clearerr(FILE *stream)
clearerr函数用于清除与流stream相关的文件结束指示符和错误指示符。
int feof(FILE *stream)
feof函数用于在与stream流相关的文件结束指示符被设置时返回一个非0值。
int ferror(FILE *stream)
ferror函数用于在与stream相关的文件出错指示符被设置时返回一个非0值。
void perror(const char *s)
perror(s)函数用于输出字符串s以及与全局变量errno中的整数值相对应的出错信息,具体出错信息的内容依赖于实现。该函数的功能类似于
fprintf(stderr, "%s:%s\n", s, "出错信息")
参见B.3节所介绍的函数strerror。
B.2 字符类测试:<ctype.h>
头文件<ctype.h>中说明了一些用于测试字符的函数。每个函数的变元均为int 类型,变元的值必须是EOF或可用unsigned char 类型表示的字符,函数的返回值为int 类型。如果变元c满足所指定的条件,那么函数返回非0值(表示真);否则返回值为0(表示假)。这些函数如下:
isalnum(c): 函数isalpha(c)或isdigit(c)为真。
isalpha(c): 函数isupper(c)或islower(c)为真。
iscntrl(c): c为控制字符。
isdigit(c): c为十进制数字。
isgraph(c): c是除空格外的可打印字符。
islower(c): c是小写字母。
isprint (c): c是包括空格的可打印字符。
ispunct(c): c是除空格、字母和数字外的可打印字符。
isspace(c): c是空格、换页符、换行符、回车符、横向制表符和纵向制表符。
isupper(c): c是大写字母。
isxdigit(c): c是十六进制数字。
在七位ASCII字符集中,可打印字符是从0x20('')到0x7E('~')之间的字符;控制字符是从0(NUL)到0x1F(US)之间的字符和字符0x7F(DEL)。
另外,还有两个函数用于字母的大小写间的转换:
int tolower(int c) 把c转换为小写字母
int toupper(int c) 把c转换为大写字母
如果c是一个大写字母,那么tolower(c)返回对应的小写字母;否则返回c。如果c是一个小写字母,那么toupper(c)返回对应的大写字母;否则返回c。
B.3 字符串函数:<string.h>
在头文件<string.h>中定义了两组字符串函数。第一组函数的名字以str开头;第二组函数的名字以mem开头。只有函数memmove对重叠对象间的拷贝进行了定义,而其他函数则未对重叠对象间的拷贝进行定义。比较类函数将其变元视为unsigned char类型的数组。
在下面的各个函数中,变量s和t的类型为char *,cs和ct的类型为const char *,n的类型为size_t,c的类型为int 已被转换成char 类型)。
char *strcpy(s, ct)
strcpy函数用于把字符串ct(包括'\0')拷贝到字符串s当中,并返回s。
char *strncpy(s, ct, n)
strncpy函数用于把字符串ct中最多n个字符拷贝到字符串s中,并返回s。如果ct中少于n个字符,那么就用一个'\0'补充。
char *strcat(s, ct)
strcat函数用于把字符串ct连结到s的尾部,并返回s。
char *strncat(s, ct, n)
strncat函数用于把字符串ct中最多n个字符连结到字符串s的尾部,并以'\0'结束;返回s。
int strcmp(cs, ct)
strcmp函数用于比较字符串cs和ct;当cs<ct时它返回一个负数;当cs>ct时它返回一个正数;当cs==ct时它返回0。
int strncmp(cs, ct, n)
strncmp函数用于将字符串cs中至多n个字符与字符串ct相比较。当cs<ct时它返回一个负数;当cs>ct时它返回一个正数;当cs==ct时它返回0。
char *strchr(cs, c)
strchr函数用于返回一个指向字符串cs中字符c第一次出现的位置的指针;如果cs中不包含c,那么该函数返回NULL。
char *strrchr(cs, c)
strrchr函数用于返回一个指向字符串cs中字符c最后一次出现的位置的指针;如果cs中不包含c,那么函数返回NULL。
size_t strspn(cs, ct)
strspn函数用于返回字符串cs中由字符串ct中的字符构成的第一个子串的长度。
size_t strcspn(cs, ct)
strcspn函数用于返回字符串cs中由不在字符串ct中的字符组成的第一个字串的长度。
char *strpbrk(cs, ct)
strpbrk函数用于返回指向字符串ct中的任意字符第一次出现在字符串cs中的位置的指针;如果cs中没有与ct相同的字符,那么返回NULL。
char *strstr(cs, ct)
strstr函数用于返回指向字符串ct第一次出现在字符串cs中的位置的指针;如果cs中不包含字符串ct,那么返回NULL。
size_t strlen(cs)
strlen函数用于返回字符串cs的长度。
char *strerror(n)
strerror函数用于返回指向与错误序号n对应的错误信息字符串的指针(错误信息的具体内容依赖于实现)。
char *strtok(s, ct)
strtok函数在s中搜索由ct中的分界符界定的单词。见下面的讨论。
对strtok(s,ct)的一系列调用将把字符串s分成许多单词,这些单词以ct中的字符为分界符。第一次调用时s非空,它搜索s,找出由非ct中的字符组成的第一个单词,将s中的下一个字符替换为'\0',并返回指向单词的指针。随后,每次调用strtok函数时(由s的值是否为NULL指示),均返回下一个由非ct中的字符组成的单词。当s中没有这样的单词时返回NULL。每次调用时字符串ct可以不同。
以mem开头的函数以字符数组的方式操作对象,其主要目的是提供一个高效的函数接口。在下面的函数中,s和t的类型均为void *,cs和ct的类型均为const void *,n的类型为size_t ,c的类型是int (被转换为unsigned char 类型)。
void *memcpy(s, ct, n)
memcpy函数用于把字符串ct中的n个字符拷贝到s当中,并返回s。
void *memmove(s, ct, n)
memmove函数的功能与memcpy相似,不同之处是当发生对象重叠时,该函数仍能正确执行。
int memcmp(cs, ct, n)
memcmp函数用于把cs的前n个字符与ct相比较,其返回值与strcmp的返回值相同。
void *memchr(cs, c, n)
memchr函数用于返回指向c在cs中第一次出现的位置指针,如果在cs的前n个字符当中找不到匹配,那么返回NULL。
void *memset(s, c, n)
memset函数用于把s中的前n个字符替换为c,并返回s。
B.4 数学函数:<math.h>
头文件<math.h>中说明了数学函数和宏。
宏EDOM和ERANGE(定义在头文件<error.h>中)是两个非0整常量,用于引发各个数学函数的定义域错误和值域错误;HUGE_VAL是一个double类型的正数。当变元取值在函数的定义域之外时,就会出现定义域错误。在发生定义域错误时,全局变量errno的值被置为EDOM,函数的返回值视具体实现而定。如果函数的结果不能用double类型表示,那么就会发生值域错误。
当结果上溢时,函数返回HUGE_VAL并带有正确的符号(正负号),errno的值被置为ERANGE。
当结果下溢时,函数返回0,而errno是否被设置为ERANGE视具体实现而定。
在下列函数中,x和y的类型为double,n的类型为int ,所有函数的返回值的类型均为double。三角函数的角度用弧度表示。
sin(x) x的正弦。
cos(x) x的余弦。
tan(x) x的正切。
asin(x) sin(x)的倒数,值域为[-/2,π/2],其中x[-1,1]。
acos(x) cos(x)的倒数,值域为[0,π],其中x[-1,1]。
atan(x) tan(x)的倒数,值域为[-π/2,π/2]。
atan2(y, x) tan(y/x)的倒数,值域为[-π,π]。
sinh(x) x的双曲正弦。
cosh(x) x的双曲余弦。
tanh(x) x的双曲正切。
exp(x) 幂函数e^x。
log(x) 自然对数ln(x),其中x>0。
log10(x) 以10为底的对数log10(x),其中x>0。
pow(x, y) x^y。如果x=0且y≤0或者如果x<0且y不是整数,那么产生定义域错误。
sqrt(x) x的平方根,其中x≥0。
ceil(x) 不小于x的最小整数,x的类型为double。
floor(x) 不大于x的最大整数,x的类型为double。
fabs(x) 绝对值|x|。
ldexp(x, n) x·2^n。
frexp(x, int *exp) 把x分成一个在[1/2, 1)区间的真分数和一个2的幂数。将真分数返回,幂数保存在*exp中。如果x为0,那么这两部分均为0。
modf(x, double*ip) 把x分成整数和小数两部分,两部分均与x有相同的正负号。函数返回小数部分,整数部分保存在*ip中。
fmod(x, y) 求x/y的浮点余数,符号与x相同。如果y为0,那么结果由具体实现而定。
B.5 实用函数:<stdlib.h>
在头文件<stdlib.h>中说明了用于数值转换、内存分配以及具有其他相似任务的若干函数。
double atof(const char *s)
atof函数用于把字符串s转换成double类型;该函数等价于
strtod(s, (char **)NULL)。
int atoi(const char *s)
atoi函数用于把字符串s转换成int 类型;该函数等价于
(int)strtol(s, (char **)NULL, 10)。
long atol(const char *s)
atol函数用于把字符串s转换成long 类型;该函数等价于
strtol(s, (char **)NULL, 10)
double strtod(const char *s, char **endp)
strtod函数用于把字符串s的前缀转换成double类型,在转换时跳过s的前导空白符。除非endp为NULL,否则该函数把指向s中未转换部分(s的后缀部分)的指针保存在*endp中。如果结果上溢,那么函数就返回带有适当符号的HUGE_VAL;如果结果下溢,那么函数返回0。在这两种情况下,errno均被置为ERANGE。
long strtol(const char *s, char **endp, int base)
strtol函数用于把字符串s的前缀转换成long 类型,在转换时跳过s的前导空白符。除非endp为NULL,否则该函数把指向s中未转换部分(s的后缀部分)的指针保存在*endp中。如果base的取值在2到36之间,那么转换的输入是以该基数进行的;如果base的取值为0,那么基数为八进制、十进制或十六进制。以0为前导的是八进制,以0x或0X为前导的是十六进制。无论在哪种情况下,字母均表示10到base-1之间的数字。如果base值是16,可以加上前导0x或0X。如果结果上溢,那么函数依据结果的符号返回long _MAX或long _MIN,同时将errno的值置为ERANGE。
unsigned long strtoul(const char *s, char **endp, int base)
strtoul函数的功能与strtol函数相同,只是结果为unsigned long 类型,错误值为Ulong_MAX。
int rand(void )
rand函数用于产生一个0到RAND_MAX之间的伪随机整数。RAND_MAX的取值至少为32767。
void srand(unsigned int seed)
srand函数用参数seed作为生成新的伪随机数序列的种子。种子seed的初值为1。
void *calloc(size_t nobj, size_t size)
calloc函数为由nobj个大小为size的对象组成的数组分配足够的内存,并返回指向所分配区域的第一个字节的指针;若内存不足以满足要求,则返回NULL。该空间的初始大小为0字节。
void *malloc(size_t size)
malloc函数用于为大小为size的对象分配足够的内存,并返回指向所分配区域的第一个字节的指针;若内存不足以满足要求,则返回NULL。不对分配的内存区域进行初始化。
void *realloc(void *p, size_t size)
realloc函数用于将p所指向的对象的大小改为size个字节。如果新分配的内存比原内存大,那么原内存的内容保持不变,增加的空间不进行初始化。如果新分配的内存比原内存小,那么新内存保持原内存区单元的内容。realloc函数返回指向新分配空间的指针;若不能满足要求,则返回NULL,在这种情况下,原p指向的内存区保持不变。
void free(void *p)
free函数用于释放p所指向的内存空间;当p的值为NULL时,该函数不起作用。p必须指向先前用动态分配函数malloc、realloc或calloc分配的空间。
void abort(void )
abort函数用于使程序非正常终止。其功能与raise(SIGABRT)类似。
void exit(int status)
exit函数用于使程序正常终止。atexit函数以与注册的相反顺序被调用,此时,所有已打开的文件被刷新,所有已打开的流被关闭,控制返回给环境。status的值如何被返回依具体的实现而定,但用0值表示终止成功。也可使用值EXIT_SUCCESS和EXIT_FAILURE。
int atexit(void (*fcn)(void ))
atexit函数用于注册在程序正常终止时所要调用的函数fcn。如果注册失败,那么返回非0值。
int system(const char *s)
system函数用于把字符串s传送给执行环境。如果s的值为NULL,那么在存在命令处理程序时,返回非0值。如果s的值不是NULL,那么返回值与具体的实现有关。
char *getenv(const cahr*name)
getenv函数用于返回与name有关的环境字符串。如果该字符串不存在,那么返回NULL。其细节与具体的实现有关。
void *bsearch(const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *keyval, const void *datum)
bsearch函数用于在base[0]...base[n-1]之间查找与*key匹配的项。cmp函数在其第一个变元(查找关键字,keyval)小于第二个变元(表项,datum)时必须返回一个负值;在其第一个变元等于第二个变元时必须返回零;在其第一个变元大于第二个变元时必须返回一个正值。数组base中的项必须按升序排列。bsearch函数返回一个指向匹配项的指针;若不存在匹配的项则返回NULL。
void qsort(void *base, size_t n, size_t size, int (*cmp)(const void *, const void *))
qsort函数用于对由n个大小为size的对象构成的数组base进行升序排序。比较函数cmp与bsearch函数中的描述相同。
int abs(int n)
abs函数用于返回其int 类型变元n的绝对值。
long labs(long n)
labs函数用于返回其long 类型变元n的绝对值。
div_t div(int num, int denom)
div函数用于求num/denom的商和余数,并把结果分别保存在结构类型div_t的两个int 类型的数quot和rem中。
ldiv_t ldiv(long num, long denom)
ldiv函数用于求num/denom的商和余数,并把结果分别保存在结构类型ldiv_t的两个long类型的数quot和rem中。
B.6 诊断:<assert.h>
assert宏用于为程序增加诊断功能:
void assert(int 表达式)
当
assert(表达式)
执行时,如果表达式的值为0,那么assert宏将在标准出错输出流stderr输出一条如下所示的信息:
Assertion failed:表达式, FILE 文件名, linennn
然后调用abort终止执行。其中的源文件名和行号来自于预处理程序宏__FILE __和__LINE__。
如果在头文件<assert.h>被包含时定义了宏NDEBUG,那么宏assert将被忽略。
B.7 变长变元表:<stdarg.h>
头文件<stdarg.h>提供了依次处理含有未知数目和类型的函数变元表的功能。
假设函数f含有可变数目的变元,lastarg是它的最后一个有名参数,然后在f内说明一个类型为va_list的变量ap,它将依次指向每个变元:
va_list ap;
在访问任何未命名的变元前必须用va_start宏对ap进行初始化:
va_start(va_list ap, lastarg);
此后,宏va_arg的每次执行将产生一个与下一个未命名的变元有相同类型和值的值,它同时还修改ap,以使下一次使用va_arg时返回下一个变元:
type va_arg(va_list ap, 类型);
当所有的变元被处理完毕之后f要退出执行以前,必须调用一次宏va_end:
void va_end(va_listap);
B.8 非局部跳转:<setjmp.h>
头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别地,它允许立即从一个多层嵌套的函数调用中返回。
int setjmp(jmp_buf env)
setjmp宏用于把当前状态信息保存到env中,供以后long jmp函数恢复状态信息时使用。如果是直接调用setjmp,那么返回值为0;如果是由于调用long jmp而调用setjmp,那么返回值非0。
setjmp只能在某些特定的情况下调用,如在if语句、switch语句及循环语句的条件测试部分以及一些简单的关系表达式中:
if(setjmp(env)==0)
/*直接调用setjmp时进行的处理*/
else
/*由于调用longjmp函数而进行的处理*/
void longjmp(jmp_buf env, int val)
long jmp用于恢复由最近一次调用setjmp时所保存到env中的状态信息。当它执行完时,程序就像setjmp宏调用刚刚执行完并返回非0值val那样继续执行。包含setjmp宏调用的函数的执行不必已经终止。所有可访问的对象的值都与调用long jmp时相同,唯一的例外是,那些调用setjmp宏的函数中的非volatile自动变量如果在调用setjmp宏后有了改变,那么就变成未定义的。
B.9 信号处理:<signal.h>
头文件<signal.h>中提供了一些用于处理程序运行期间所引发的异常条件的功能,如处理来源于外部的中断信号或程序执行期间出现的错误等异常事件。
void (*signal(int sig, void (*handler)(int)))(int)
signal用于确定处理以后的信号的方法。如果handler的值是SIG_DFL,那么就采用由实现定义的缺省行为;如果handler的值是SIG_IGN,那么就忽略该信号;否则,调用handler所指向的函数(变元的类型为信号的类型)。有效的信号包括:
SIGABRT 异常终止,如由abort发出的信号。
SIGFPE 算术运算出错,如除数为0或溢出。
SIGILL 非法函数映像,如非法指令。
SIGint 交互式意图,如中断。
SIGSEGV 非法访问存储器,如访问不存在的内存单元。
SIGTERM 发送给本程序的终止请求信号
signal对指定信号返回handler的前一个值;如果出现错误,那么返回值为SIG_ERR。
当随后出现信号sig时,该信号被恢复为其缺省行为,然后调用信号处理函数,如(*handler)(sig)。如果从信号处理程序中返回,那么程序就从发信号时的位置重新开始执行。
信号的初始状态由实现定义。
int raise(int sig)
raise用于向程序发送信号sig。如果发送不成功,就返回一个非0值。
B.10 日期与时间函数:<time.h>
头文件<time.h>中说明了一些用于处理日期与时间的类型和函数。其中的一部分函数用于处理当地时间,因为时区等原因,当地时间与日历时间可能不相同。clock_t和time_t是两个用于表示时间的算术类型,而struct tm则用于存放日历时间的各个成分。tm的各个成员的用途及取值范围如下:
int tm_sec; 从当前分钟开始经过的秒数(0,61)。
int tm_min; 从当前这小时开始经过的分钟数(0,59)。
int tm_hour; 自午夜(0,23)。
int tm_mday; 本月中的天数(1,31)。
int tm_mon; 从1月起经过的月数(0,11)。
int tm_year; 从1900年起经过的年数。
int tm_wday; 从星期天起经过的天数(0,6)。
int tm_yday; 从1月1日起经过的天数(0,365)。
int tm_isdst; 夏令时标记。
其中,tm_is dst在使用夏令时时其值为正,在不使用夏令时时其值为0。如果该信息不能使用,那么tm_is dst的值为负。
clock_t clock(void )
clock函数用于返回程序自开始执行到目前为止所占用的处理机时间;如果处理机时间不可使用,那么返回值为-1。clock()/CLOCKS_PER_SEC是以秒为单位表示的时间。
time_t time(time_t *tp)
time函数用于返回当前日历时间;如果日历时间不能使用,那么返回值为-1。如果tp的值不为NULL,那么同时把返回值赋给*tp。
double difftime(time_t time2, time_t time1)
difftime函数用于返回time2-time1的值(以秒为单位)。
time_t mktime(struct tm *tp)
mktime函数用于将结构*tp中的当地时间转换为time_t类型的日历时间(可被time函数使用)。结构中各成分具有上面所示范围之内的取值。mktime函数返回转换成得到的日历时间;如果该时间不能表示,那么就返回-1。
下面四个函数用于返回指向可被其他调用重写的静态对象的指针。
char *asctime(const struct tm *tp)
asctime函数用于将结构*tp中的时间转换成如下所示的字符串形式:
Sun Jan 3 15:14:13 1998\n\0
char *ctime(const time_t *tp)
ctime函数用于将结构*tp中的日历时间转换成当地时间。它等价于如下函数调用
asctime(localtime(tp))
struct tm *gmtime(const time_t *tp)
gmtime函数用于将*tp中的日历时间转换成世界协调时(UTC)。如果UTC不能使用,那么该函数返回NULL。函数名字“gmtime”有其历史意义。
struct tm *localtime(const time_t *tp)
localtime函数用于将结构*tp中的日历时间转换成当地时间。
size_t strftime(char *s, size_t smax, const char *fmt, const struct tm *tp)
strftime函数用于根据fmt的值把结构*tp中的日期与时间信息转换成指定的格式并存储到s所指向的数组中,其中fmt类似于printf函数中的格式说明,它由0个或多个转换规格说明与普通字符组成。普通字符(包括终结行的空字符'\0')都原封不动地拷贝到s中。每个%c按照下面所描述的格式用与当地环境相适应的值来替换。写到s中的字符数不得大于smax。Strftime函数返回实际写到s中的字符数(不包括空字符'\0');如果所产生的字符数多于smax,该函数返回值为0。
在strftime函数中可以使用的转换规格说明及其所表示的含义如下:
%a 一星期中各天的缩写名。
%A 一星期中各天的全名。
%b 缩写月份名。
%B 月份全名。
%c 当地时间和日期表示。
%d 用整数表示的一个月中的某一天(01~31)。
%H 用整数表示的时(24小时制,00~23)。
%I 用整数表示的时(12小时制,01~12)。
%j 用整数表示的一年中各天(001~366)。
%m 用整数表示的月份(01~12)。
%M 用整数表示的分(00~59)。
%p 与AM与PM对应的当地表示方法。
%S 用整数表示的秒(00~61)。
%U 用整数表示一年中的星期数(00~53,将星期日看作是每周的第一天)。
%w 用整数表示一周中的各天(0~6,星期日为0)。
%W 用整数表示一年中的星期数(00~53,将星期一看作是每周的第一天)。
%x 当地日期表示。
%X 当地时间表示。
%y 不带世纪号的年份(00~99)。
%Y 完整年份表示(带世纪号)。
%Z 时区名字(在可以使用时)。
%%% 本身。
B.11 由实现定义的限制:<limits.h>和<float.h>
头文件<limits.h>中定义了用于表示整类型大小的常量。以下所列的值是可接受的最小值,在实际系统中可以使用更大的值。
CHAR_BIT 8 char类型的位数
CHAR_MAX UCHAR_MAX或SCHAR_MAX char类型的最大值
CHAR_MIN 0或SCHAR_MIN char类型的最小值
INT_MAX +32767 int类型的最大值
INT_MIN -32767 int类型的最小值
LONG_MAX +2147483647 long类型的最大值
LONG_MIN -2147483647 long类型的最小值
SCHAR_MAX +127 signed char类型的最大值
SCHAR_MIN -127 signed char类型的最小值
SHRT_MAX +32767 short类型的最大值
SHRT_MIN -32767 short类型的最小值
UCHAR_MAX 255 unsigned char类型的最大值
UINT_MAX 65535 unsigend int类型的最大值
ULONG_MAX 4294967295 unsigned long类型的最大值
USHRT_MAX 65535 unsigned short类型的最大值
下面列出的名字是<float.h>的一个子集,是与浮点算术运算相关的一些常量。给出的每个值代表相应量的一个最小取值。各个实现可以定义适当的值。
FLT_RADIX 2 指数表示的基数,如2、16
FLT_ROUNDS 加法的浮点舍入规则
FLT_DIG 6 精度的十进制数字数
FLT_EPSILON 1E-5 使1.0+x(1.0成立的最小的x
FLT_MANT_DIG 基数为FLT_RADIX的尾数中的数字数
FLT_MAX 1E+37 最大浮点数
FLT_MAX_EXP 使FLT_RADIXn-1可表示的最大的n
FLT_MIN 1E-37 最小规范化的浮点数
FLT_MIN_EXP 使10n为规范化数的最小的n
DBL_DIG 10 精度的十进制字数
DBL_EPSILON 1E-9 使1.0+x1.0成立的最小的x
DBL_MANT_DIG 基数为FLT_RADIX的尾数中的数字数
DBL_MAX 1E+37 最大双精度浮点数
DBL_MAX_EXP 使FLT_RADIXn-1可以正常表示的最大的n
DBL_MIN 1E-37 最小双精度浮点数
DBL_MIN_EXP 使10n为规范化数的最小的n