The Standard C Library
--------------經(jīng)典的基礎(chǔ)
C的標志庫函數(shù)是學(xué)習(xí)和使用C語言的基礎(chǔ),是編寫經(jīng)典C程序的基礎(chǔ),是學(xué)習(xí)其他計算機知識的基礎(chǔ).C標志庫中一共包含了15個頭文件:
<assert.h> <ctype.h> <stdio.h> <stdlib.h> <string.h> <limits.h> <float.h> <time.h>
<math.h> <setjmp.h> <signal.h> <stdarg.h> <stddef.h> <errno.h> <locale.h>
1:<assert.h>
NDEBUG
NDEBUG宏是調(diào)試開關(guān),當(dāng)使用#include NDEBUG時程序為非調(diào)試狀態(tài),這種狀態(tài)下調(diào)試宏assert不起作用。
assert
調(diào)試宏assert只有在程序處于調(diào)試狀態(tài)下才發(fā)揮作用,它的使用形式如下:assert(expression);當(dāng)條件為假時會在屏幕中輸出如下的調(diào)試信息:“Assertion failed:expression, file xyz, line nnn”,其中xyp是assert所在的文件名,nnn為assert在該文件中的位置。
assert宏還有許多用法,請參看《Writing Clean Code》第二章設(shè)計并使用斷言。
2:<stdio.h>
<stdio.h>下面的類型,宏,函數(shù)都是分類的
其他:
size_t sizeof返回的值
NULL 空指針
文件:
FILE 文件的類型
fpos_t 文件中指針的位置
EOF 文件末尾<0
FILENAME_MAX 文件名最大值>0
FOPEN_MAX 同時打開文件的最大值>8
SEEK_SET 文件頭
SEEK_CUR 文件當(dāng)前位置
SEEK_END 文件末尾
打開文件
FILE *fopen(const char *filename,const char *mode);
更改當(dāng)前流相關(guān)的文件
FILE *freopen(const char *filename,const char *mode,FILE *stream);
關(guān)閉文件
int fclose(FILE *stream);
清除流中的錯誤標志或文件末尾標志
void clearerr(FILE *stream);
測試流上的文件末尾標志
int feof(FILE *stream);
測試流上的錯誤標志
int ferror(FILE *stream);
將一個字符放回到流中
int ungetc(int c, FILE *stream);
從流中讀一個字符
int fgetc(FILE *stream);
int getc(FILE *stream);/* 與fgetc相同但是可以用宏實現(xiàn)該函數(shù) */
寫一個字符到一個流
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
從流中獲取一個字符串
char *fgets(char *s, int n, FILE *stream);
寫一個字符串到一個流
int fputs(const char *s, FILE *stream);
打印一個格式化數(shù)據(jù)到一個流
int fprintf(FILE *stream,const char *format, ...);
使用一個參量列表指針格式化到流的數(shù)據(jù)
int vfprintf(FILE *stream,const char *format, va_list ap);
從一個流中讀取格式化數(shù)據(jù)
int fscanf(FILE *stream, const char *format, ...);
從一個流中讀數(shù)據(jù)
size_t fread(char *buffer,size_t size,size_t count,FILE *stream);
寫數(shù)據(jù)到一個流
int fwrite(const char *buffer, size_t size, size_t count,
FILE *stream);
獲取流的文件位置指示符
int fgetpos(FILE *stream, fpos_t *pos);
設(shè)置流位置指示符
int fsetpos(FILE *stream, const fpos_t *pos);
移動文件指針到一個指定的位置
int fseek(FILE *stream, long offset, int origin);
獲得文件指針相對于文件頭的偏移量
long ftell(FILE *stream);
重新定位一個文件指針到文件開頭
void rewind(FILE *steam);
刪除一個文件
int remove(const char *path);
更改一個文件或目錄
int rename(const char *oldname, const char *newname);
緩沖區(qū):
_IOFBF
_IOLBF
_IONBF 緩沖區(qū)類型
BUFSIZE 緩沖區(qū)尺寸>=256
刷新一個流并清空與流相關(guān)的緩沖區(qū)的內(nèi)容
int fflush(FILE *stream);
控制流的緩沖區(qū),已經(jīng)被setvbuf代替
void setbuf(FILE *stream, char *buffer);
控制流的緩沖區(qū)類型和緩沖區(qū)大小
int setvbuf(FILE *stream, char *buffer, int mode, size_t size);
將一個格式化數(shù)據(jù)寫入一個字符串
int sprintf(char *buffer, const char *format, ...);
從字符串中讀格式化數(shù)據(jù)
int sscanf(const char *buffer, const char *format, ...);
從參量列表指針格式化到字符串
int vsprintf(char *buffer, const char *format, va_list ap);
臨時文件
L_tmpnam 臨時文件名長度>0
TMP_MAX 產(chǎn)生唯一文件名的最大數(shù)目>=25
以二進制讀寫的方式建立一個臨時文件
FILE *tmpfile(void);
建立一個臨時文件名
char *tmpname(char *string);
標準流:
stdin 標準輸入流
stdout 標準輸出流
stderr 標準錯誤輸出流
從stdin獲得一個字符
int getchar(void);
把字符寫道stdout
int putchar(int c);
從stdin中獲取一行
char *gets(char *buffer);
寫一個字符串到stdout
int puts(const char *string);
打印一個錯誤消息到stderr
void perror(const char *error);
打印格式化數(shù)據(jù)到stdout
int printf(const char *format, ...);
從stdin讀格式化數(shù)據(jù)
int scanf(const char *format, ...);
從參量列表指針格式化到stdout
int vprintf(const char *format, va_list ap);
3:<stdlib.h>
<stdlib.h>中定義的函數(shù)都是工具類的函數(shù)可以分類學(xué)習(xí)
其他:
NULL
size_t
執(zhí)行一個系統(tǒng)命令
int system(const char *command);
程序控制:
EXIT_SUCCESS
EXIT_FAILURE exit函數(shù)的推出參數(shù)
終止當(dāng)前進程并返回一個錯誤代碼
void abort(void);
在推出時執(zhí)行指定的函數(shù)
int atexit(void(*func)(void));
終止調(diào)用進程
void exit(int status);
數(shù)學(xué)工具:
div_t 函數(shù)div的返回類型
ldiv_t 函數(shù)ldiv的返回類型
RAND_MAX rand函數(shù)返回的最大值
產(chǎn)生一個偽隨機數(shù)
int rand(void);
設(shè)置一個隨機起始點
void srand(unsigned int seed);
計算絕對值
int abs(int i);
計算一個long整數(shù)的絕對值
long labs(long l);
執(zhí)行一個快速排序
void qsort(void *base, size_t count, size_t size,
int (*compare)(const void *elem1, const void *elem2));
執(zhí)行一個排序數(shù)組的二叉查找
void *bsearch(const void *key, const void *base,
size_t count, size_t size,
int(*compare)(const void *elem1,const void *elem2)
);
計算兩個數(shù)的商與余數(shù)
div_t div(int number, int denom);
計算兩個long整數(shù)的商和余數(shù)
ldiv_t ldiv(long number, long denom);
字符/字符串工具
wchar_t 寬字符寬度
MB_CUR_MAX 多字節(jié)字符中的最大字節(jié)數(shù)
將字符串轉(zhuǎn)換成雙精度
double atof(const char *string);/*可含有非數(shù)字字符 */
將字符串轉(zhuǎn)換成整數(shù)
int atoi(const char *string);
將字符串轉(zhuǎn)換成長整形
long atol(const char *string);
把字符串轉(zhuǎn)換成一個雙精度值
double strtod(const char *string, char **endptr);/*可以含有非數(shù)字
字符,被截掉的字符存在endptr中*/
把字符串轉(zhuǎn)換成長整形
long strtol(const char *string, char **endptr, int base);
把字符串轉(zhuǎn)換成無符號長整形
unsigned long strtoul(const char *string, char **endptr, int base);
獲取長度和確定一個多字節(jié)字符的有效性
int mblen(const char *s, size_t count);
將一個多字節(jié)字符序列轉(zhuǎn)換成寬字符序列
size_t mbstowcs(wchar_t *wcstr, const char *mbstr, size_t count));
將一個多字節(jié)字符轉(zhuǎn)換成對應(yīng)的寬字符
int mbtowc(wchar_t *wchar, const char *mbchar, size_t count));
將一個寬字符序列轉(zhuǎn)換成一個多字節(jié)字符序列
size_t wcstombs(char *mbstr, wchar_t *wcstr, size_t count));
將一個寬字符轉(zhuǎn)換成一個多字節(jié)字符
int wctomb(char *mbchar, wchar_t wchar);
內(nèi)存管理工具:
分配內(nèi)存塊
void *malloc(size_t size);
在內(nèi)存中分配一個數(shù)組并初始化為0
void *calloc(size_t count, size_t size);
重新分配內(nèi)存塊
void *recalloc(void *memblock, size_t size);
釋放一塊內(nèi)存
void free(void *memblock);
環(huán)境工具:
從當(dāng)前環(huán)境中取得一個值
char *getenv(const char *varname);
4<ctype.h>
<ctype.h>頭文件中定義了有關(guān)于字符操作的函數(shù)
判斷一個字符是否為控制字符(0x00 ~ 0x1f 或 0x7f)
int iscntrl(int c);
判斷一個字符是否為空白字符(0x09 ~ 0x0d 或 0x20)
int isspace(int c);
判斷一個字符是否為可打印字符(0x20 ~ 0x7e)
int isprint(int c);
判斷一個字符是否為非空格的其他可打印字符(0x21 ~ 0x7e)
int isgraph(int c);
判斷一個字符是否為標點字符
int ispunct(int c);
判斷一個字符是否為字母數(shù)字字符
int isalnum(int c);
判斷一個字符是否為十進制數(shù)字字符
int isdigit(int c);
判斷一個字符是否為十六進制數(shù)字字符
int isxdigit(int c);
判斷一個字符是否為字母字符
int isalpha(int c);
判斷一個字符是否為大寫字母字符
int isupper(int c);
判斷一個字符是否為小寫字母字符
int islower(int c);
轉(zhuǎn)換字符為小寫
int tolower(int c);
轉(zhuǎn)換字符為大寫
int toupper(int c);

5<string.h>:
<string.h>中聲明的函數(shù)都是關(guān)于c字符串和內(nèi)存操作的函數(shù)
其他:
NULL
size_t
內(nèi)存操作:
查找內(nèi)存塊中的一個字符
void *memchr(const void *buffer, int c, size_t count);
比較兩個內(nèi)存塊中的字符
int memcmp(const void *buffer1,const void *buffer2,size_t count);
在在內(nèi)存塊之間拷貝字節(jié)
void *memcpy(void *dest, const void *src, size_t count);
移動內(nèi)存塊
void *memmove(void *dest, const void *src, size_t count);
用指定的字符填充內(nèi)存
void *memset(void *dest, int c, size_t count);
對于以上的函數(shù)中的size_t count項使用需注意了
當(dāng)你按如下方式使用是錯誤的
str = (char *)malloc(sizeof(char)*81);
strp = (char *)memchr(str, ‘u’, sizeof(str));
free(str);
這是錯誤的str是指針它的長度不是整個字符串的長度,所以strp得不到正確的結(jié)果
應(yīng)改為一個確定的數(shù)或者是實際數(shù)組的長度如strlen(str).
字符串操作:
字符串拼接
char *strcat(char *dest, const char *src);
向一個字符串末尾添加指定長度的字符串
char *strncat(char *dest, const char *src, size_t n);
在字符串中查找一個字符
char *strchr(const char *str, int c);
在一個字符串中查找一個字符最后一次出現(xiàn)
char *strrchr(const char *str, int c);
比較字符串
int strcmp(const char *str1, const char *str2);
比較兩個字符串中指定長度的子串的大小
int strncmp(const char *str1, const char *str2, size_t n);
使用指定場所的信息比較字符串
int strcoll(const char *str1, const char *str2);
基于指定場所轉(zhuǎn)換一個字符串
size_t strxfrm(char *dest, const char *src, size_t n);
拷貝一個字符串
char *strcpy(char *dest, const char *src);
將源字符串中指定長度的子串拷貝到目的串中
char *strncpy(char *dest, const char *src, size_t n);
查找一個子串
char *strstr(const char *string, const char *str);
查找string包含str中包含的字符的長度,例如:
string = “cabbage”; str = “abc”; return value = 5;
string = “cab bage”; str = “abc”; return value = 3;
string = “cafbbage”; str = “abc”; return value = 2;
string = “vcabbage”; str = “abc”; return value = 0;
size_t strspn(const char *string, const char *str);
在一個字符串中查找另一字符串的任意字符第一次出現(xiàn)的下標例如
string = “cabbage”; str = “ag”; return value = 1;
string = “xcabbage”; str = “ag”; return value = 2;
size_t strcspn(const char *string, const char *str);
返回在string中出現(xiàn)str字符集中的第一個字符的位置例如:
string = “kdkow adkf akkei”;str = “aeiw”;
return value = “w adkf akkei”;
char *strpbrk(const char *string, const char *str);
查找字符串中下一個語言符號
所謂的語言符號就是指用戶定義的表示一個意義的整體,string是字符串,str是包含分割語言符合的分隔符的集合.使用方法例如:
token = strtok(string,str);
while(token != NULL)
{
puts(token);
token = strtok(NULL, str);
}
如
string = “kks\niiwo jfie\twlk,diwpob.owf’ksif\nli”;
str = “ \n\t,.’”;
結(jié)果為:
kks
iiwo
jfie
wlk
diwpob
owf
ksif
li
如
str = “w”;
結(jié)果為:
kks\nii
o jfie\t
lk,di
pob.o
f’ksif\nli
char *strtok(char *string, const char *str);
通過系統(tǒng)錯誤編號來獲得系統(tǒng)錯誤消息
char *strerror(int errorcode);
獲取字符串有效長度(不包括’\0’)
size_t strlen(const char *str);
6<limits.h>:
<limits.h> 中定義了整形的各種形式的邊界值
char
CHAR_BIT 一個char占的位數(shù)
MB_LEN_MAX 多字節(jié)中char占的字節(jié)數(shù)
CHAR_MAX
CHAR_MIN
SCHAR_MAX
SCHAR_MIN
UCHAR_MAX
short
SHRT_MAX
SHRT_MIN
USHRT_MAX
int
INT_MAX
INT_MIN
UINT_MAX
long
LONG_MAX
LONG_MIN
ULONG_MAX
7<stddef.h>:
NULL
size_t
wchar_t
ptrdiff_t 指針之間的差值
size_t offsetof(structName,memberName); 結(jié)構(gòu)成員相對于結(jié)構(gòu)的偏移量
8<time.h>
NULL
size_t
CLOCKS_PER_SEC 每秒的時鐘數(shù)
CLK_TCK 每秒的時鐘數(shù)被CLOCKS_PER_SEC代替
clock_t clock函數(shù)的返回類型表示進程的逝去時鐘數(shù)
time_t time等函數(shù)的返回值表示日歷時間
struct tm
{
int tm_sec; 秒(0-59)
int tm_min; 分鐘(0-59)
int tm_hour; 小時(0-24)
int tm_mday; 月中的天數(shù)(多少號)(1-31)
int tm_mon; 月份(0-11)
int tm_year; 年份從1900年開始
int tm_wday; 星期(0-6,星期日=0)
int tm_yday; 一年中的日期(0-365,1月1號 = 0)
int tm_isdst; 夏令時(正數(shù)有效,0無效,負數(shù)未定義)
};
返回調(diào)用進程使用的時鐘數(shù)
clock_t clock(void);
獲取系統(tǒng)時間(從1970,1,1 00:00:00 開始到現(xiàn)在的的秒數(shù))
timer可以為NULL表示只返回不存儲
time_t time(time_t *timer);
返回兩個時間的差值
double difftime(time_t time1, time_t time2);
將time_t轉(zhuǎn)換成字符串
char *ctime(const time_t *timer);
轉(zhuǎn)換一個時間值有time_t轉(zhuǎn)換到struct tm
struct tm *locattime(const time_t *timer);
gmtime使用UTC世界時間代碼而不是本地時間
struct tm *gmtime(const time_t *timer);
將struct tm轉(zhuǎn)換成time_t
time_t mktime(struct tm *timer);
localtime gmtime mktime使用同一個struct tm靜態(tài)結(jié)構(gòu).每次調(diào)用前都清除其中的容
將struct tm轉(zhuǎn)換成字符串
char *asctime(const struct tm *timer);
格式化一個時間字符串
size_t strftime(char *dest,size_t size,const char *format,
const struct tm *timer);

9<float.h>:
<float.h>與<limits.h>一樣是定義邊界值的,<float.h>定義的是浮點數(shù)的邊界值
double
DBL_DIG double小數(shù)點后面精確的位數(shù)
DBL_EPSILON 小的正數(shù),double的0跨度值
DBL_MANT_DIG 尾數(shù)中的位數(shù)
DBL_MAX 最大值
DBL_MAX_10_EXP 最大10進制指數(shù)
DBL_MAX_EXP 最大2進制指數(shù)
DBL_MIN 最小值
DBL_MIN_10_EXP 最小10進制指數(shù)
DBL_MIN_EXP 最小2進制指數(shù)
float
FLT_DIG float小數(shù)點后面精確的位數(shù)
FLT_EPSILON 小的正書,float的0跨度值
FLT_MANT_DLG 尾數(shù)中的位數(shù)
FLT_MAX 最大值
FLT_MAX_10_EXP 最大10進制指數(shù)
FLT_MAX_EXP 最大2進制指數(shù)
FLT_MIN 最小值
FLT_MIN_10_EXP 最小10進制指數(shù)
FLT_MIN_EXP 最小2進制指數(shù)
FLT_RADIX 進制基數(shù)
FLT_ROUNDS 加法舍入
long double
LDBL_DIG long double小數(shù)點后面精確的位數(shù)
LDBL_EPSILON 小的正數(shù),long double的0跨度值
LDBL_MANT_DLG 尾數(shù)中的位數(shù)
LDBL_MAX 最大值
LDBL_MAX_10_EXP 最大10進制指數(shù)
LDBL_MAX_EXP 最大2進制指數(shù)
LDBL_MIN 最小值
LDBL_MIN_10_EXP 最小10進制指數(shù)
LDBL_MIN_EXP 最小2進制指數(shù)
10<math.h>
<math.h>中定義了數(shù)學(xué)函數(shù)
HUGE_VAL 最大的可表示的雙精度值,這個值是由許多數(shù)學(xué)函數(shù)錯誤時返回的,有的函數(shù)返回-HUGE_VAL
EDOM 當(dāng)傳遞的參數(shù)類型或數(shù)值錯誤時errno被賦予這個值
ERANGE 當(dāng)數(shù)值超出浮點數(shù)的范圍時errno被賦予這個值
三角函數(shù)
計算正弦
double sin(double x);
計算雙曲線的正弦
double sinh(double x);
計算余弦
double cos(double x);
計算雙曲線余弦
double cosh(double x);
計算正切
double tan(double x);
計算雙曲線正切
double tanh(double x);
計算反余弦
double acos(double x);
計算反正弦
double asin(double x);
計算反正切
double atan(double x);
計算y/x的反正切
double atan2(double y, double x);
冪函數(shù)
計算x的y次冪
double pow(double x, double y);
計算平方根
double sqrt(double x);
計算指數(shù)值
double exp(double x);
計算自然對數(shù)
double log(double x);
計算以10為底的對數(shù)
double log10(double x);
浮點數(shù)操作函數(shù)
返回大于或等于x的最小整數(shù)
double ceil(double x);
計算浮點數(shù)的絕對值
double fabs(double x);
返回小于等于x的最大整數(shù)
double floor(double x);
計算x/y的余數(shù)
double fmod(double x, double y);
獲得一個浮點數(shù)的尾數(shù)和指數(shù)
double frexp(double x, int *expptr);
從尾數(shù)和指數(shù)計算一個實數(shù)
double ldexp(double x, int exp);
把一個浮點數(shù)分解成小數(shù)和整數(shù)
double modf(double x, int *intptr);
11<errno.h>
errno 各種錯誤條件的事件賦予的錯誤代碼如EDOM,ERANGE等
12<locale.h>
一個程序用于指定該程序使用哪一部分場所信息.
NULL
LC_ALL 影響所用的方面
LC_COLLATE 影響字符串校驗函數(shù)strcoll,strxfrm
LC_CTYPE 影響<ctpye.h>中定義的字符處理函數(shù)
LC_MONETARY 影響localeconv返回的錢幣格式信息
LC_NUMERIC 影響localeconv返回的非錢幣格式的使用小數(shù)的數(shù)字信息,包括格式化,字符轉(zhuǎn)換等
LC_TIME 影響strftime
struct lconv
{
成員 “C”場所值 場所范圍 成員含義
char *currency_symbol; “” LC_MONETARY 當(dāng)前場所的地方貨幣
符號
char *int_curr_symbol; “” LC_MONETARY 當(dāng)前場所的國際貨幣
符號
char *mon_decimal_point; “” LC_MONETARY 貨幣量的小數(shù)點
char *mon_grouping; “” LC_MONETARY 貨幣量每個數(shù)字組的
尺寸
char *mon_thousands_sep; “” LC_MONETARY 貨幣量小數(shù)點左邊的
數(shù)字分組字符
char *negative_sign; “” LC_MONETARY 負貨幣量表示符號的
字符串
char *positive_sign; “” LC_MONETARY 正貨幣量表示符號的
字符串
char *decimal_point; “.” LC_NUMERIC 非貨幣量的小數(shù)點
char *grouping; “” LC_NUMERIC 非貨幣量的每個數(shù)字
的尺寸
char *thousands_sep; “” LC_NUMERIC 非貨幣量小數(shù)點左邊
數(shù)字分組字符
char frac_digits; CHAR_MAX LC_MONETARY 格式化貨幣量中小數(shù)
點右邊的數(shù)字位數(shù)
char int_frac_digits; CHAR_MAX LC_MONETARY 國際格式化貨幣量中
小數(shù)點右邊的數(shù)字位
數(shù)
char n_cs_precedes; CHAR_MAX LC_MONETARY 如果貨幣符號位于負
格式貨幣量之前,它
設(shè)置為1;如果符號在
值以后,設(shè)置為0
char n_sep_by_space; CHAR_MAX LC_MONETARY 如果貨幣符號通過空
格從負格式貨幣量中
分離則設(shè)置為1,沒有
空格則為0
char n_sign_posn; CHAR_MAX LC_MONETARY 負格式貨幣量值正符
號的位置
char p_cs_precedes; CHAR_MAX LC_MONETARY 如果貨幣符號位于非
負格式貨幣量之前,
它設(shè)置為1,如果符號
值以后,設(shè)置為0
char p_sep_by_space; CHAR_MAX LC_MONETARY 如果貨幣符號通過空
格從非負格式貨幣量
中分離則設(shè)置為1,沒
有空格為0
char p_sign_posn; CHAR_MAX LC_MONETARY 非負格式貨幣量值正
符號的位置
};
結(jié)構(gòu)中的char *成員等于””的長度為0或不被當(dāng)前場所支持,char成員為非負數(shù)CHAR_MAX的不被當(dāng)前場所支持.
獲得場所設(shè)置的詳細信息
struct lconv *localeconv(void);
定義一個場所
char *setlocale(int category,const char *locale);
13<setjmp.h>
jmp_buf setjmp和longjmp使用的類型,用來保存和恢復(fù)應(yīng)用程序環(huán)境
保存當(dāng)前應(yīng)用程序的環(huán)境
int setjmp(jmp_buf env);
恢復(fù)棧環(huán)境和執(zhí)行場所
void longjmp(jmp_buf env, int val);
這兩個函數(shù)的使用是有順序性的一定是先調(diào)用setjmp來存儲環(huán)境變量,再通過longjmp來恢復(fù)環(huán)境變量
它的執(zhí)行過程是這樣的(:前面的時行號)
#include <stdio.h>
#include <setjmp.h>
jmp_buf ebuf;
void f2(void);
int main(void)
{
int i;
puts("1");
0: i = setjmp(ebuf);
1: if(i == 0)
{
2: f2();
3: printf("This will not be printed");
}
4: printf("%d\n",i);
return 0;
}
void f2(void)
{
5: puts("2");
6: longjmp(ebuf,100);
}
上面的函數(shù)的執(zhí)行過程是這樣的
0行第一次執(zhí)行setjmp時ebuf中保存了當(dāng)前的系統(tǒng)環(huán)境變量,并返回0.接下來執(zhí)行第1行,這是i等于0,執(zhí)行第2行由次進入了f2中,第五行向stdout中打印了2,然后第6行調(diào)用了longjmp恢復(fù)了系統(tǒng)環(huán)境變量,注意這時函數(shù)的執(zhí)行又回到了第0行而不是執(zhí)行f2后面的第3行,這時setjmp返回的函數(shù)就不是0了而是longjmp中的100,所以接下來執(zhí)行的第1行中的i等于100了直接執(zhí)行第4行.所以第3行永遠也沒有機會執(zhí)行.
14<signal.h>
信號
SIGABRT 異常中止,缺省動作是推出程序并返回推出碼3
SIGFPE 浮點錯誤,例如溢出,除0或無效操作,缺省終止程序
SIGILL 非法指令,缺省終止程序
SIGINT CTRL+C中斷,缺省調(diào)用INT23H中斷
SIGSEGV 非法存儲訪問,缺省終止程序
SIGTERM 終止請求傳送到程序,缺省終止程序
行為
SIG_DFL 使用系統(tǒng)缺省響應(yīng),如果調(diào)用程序使用流I/O,由運行庫建立緩沖區(qū)不刷新.
SIG_IGN 忽略中斷信號,這個值從不會為SIGFPE給出,因為該進程的浮點狀態(tài)無定義
SIG_ERR 錯誤.
sig_atomic_t
發(fā)送一個信號給應(yīng)用程序,如果以前使用signal安裝了一個信號處理程序則執(zhí)行該程序,沒有則執(zhí)行信號的缺省行為
int raise(int sig);
設(shè)置中斷信號處理,signo是中斷要處理的信號,必須是上面的信號之一,func是處理函數(shù)的地址或者使用上面的行為,如果func是函數(shù)的地址,則這個函數(shù)在調(diào)用signal時就被安裝.
void (*signal(int signo,void(*func)(int)))(int);
按照如下的方法使用signal函數(shù)
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
jmp_buf env;
void fpHander(int signo);
int main(void)
{
int jmpflag;
double d1,d2,r;
0: if(signal(SIGFPE,fpHander) == SIG_ERR)
{
perror("Can't install the SIGFPE hander");
abort();
}
else
{
jmpflag = setjmp(env);
if(jmpflag == 0)
{
printf("Test for div:");
scanf("%lf%lf",&d1,&d2);
1: r = d1/d2;
printf("r:%G\n",r);
printf("d2 is not 0\n");
r = d1*d2*d2*d1*d2*d2;
2: printf("r:%G\n",r);
printf("r is not overflow\n");
3: if(d2 == 0)
4: raise(SIGFPE);
}
else
{
printf("Signal fixed\n");
}
}
return 0;
}
void fpHander(int signo)
{
printf("signo:%d\n",signo);
longjmp(env,-1);
}
一般的如果讀入的d2為0的話,那么當(dāng)執(zhí)行第1行時就會引發(fā)浮點錯誤信號SIGFPE,而代用第0行安裝的函數(shù)fpHander(但是在VC中好像不行,但TC中能通過)如果不能引發(fā)SIGFPE只好自己來引發(fā)SIGFPE了第4行調(diào)用了raise來引發(fā)SIGFPE錯誤使fpHander函數(shù)執(zhí)行.
15<stdarg.h>
在這個頭文件中定義了一些宏和類型,用來實現(xiàn)可變參數(shù)函數(shù).
va_list 可變參數(shù)表類型.
va_start 設(shè)置可變參數(shù)表頭的宏
va_arg 檢索當(dāng)前參數(shù)的宏
va_end 清除可變參數(shù)列表的宏,是的函數(shù)能夠返回.