小白博客 - c语言入门
type: channel
link: https://boke.liuxiaobai.top/index.php/category/C/
items: wctype.h
items: wchar.h
items: time.h
items: string.h
items: stdlib.h
items: stdio.h
items: stdint.h
items: stddef.h
items: stdbool.h
items: stdarg.h

wctype.h
type: item
date: 2023-09-20T09:38:39+08:00
description: wctype.hwctype.h 提供 ctype.h 里面函数的宽字符版本。宽字符类型判断函数下面函数判断宽字符的类型。iswalnum() 测试宽字符是否为字母数字iswalpha() 测试宽字符是否为字母iswblank() 测试这是否是一个宽空白字符iswcntrl() 测试这是否是一个宽控制字符。iswdigit() 测试这个宽字符是否是数字iswgraph() 测试宽字符是否是可打印的非空格字符iswlower() 测试宽字符是否为小写iswprint() 测试宽字符是否可打印iswpunct() 测试宽字符是否为标点符号iswspace() 测试宽字符是否为空格iswupper() 测试宽字符是否为大写iswxdigit() 测试宽字符是否为十六进制数字wctype()，iswctype()iswctype()是上一节各种宽字符类型判断函数的通用版本，必须与wctype()配合使用。int iswctype(wint_t wc, wctype_t desc);iswctype()接受两个参数，第一个参数是一个需要判断类型的宽字符，第二个参数是宽字符类型描述，来自wctype()的返回值。如果宽字符属于指定类型，iswctype()返回一个非零值，否则返回零。wctype()用来获取某个种类宽字符的类型描述。wctype_t wctype(const char* property);wctype()的参数是一个给定的字符串，可用的值如下：alnum、alpha、blank、cntrl、digit、graph、lower、print、punct、space、upper、xdigit。wctype()的返回值的类型为 wctype_t，通常是一个整数。如果参数是一个无效值，则返回0。if (iswctype(c, wctype("digit"))) // 相当于 if (iswdigit(c))上面示例用来判断宽字符c是否为数值，相当于iswdigit()。iswctype()的完整类型判断如下。iswctype(c, wctype("alnum")) // 相当于 iswalnum(c) iswctype(c, wctype("alpha")) // 相当于 iswalpha(c) iswctype(c, wctype("blank")) // 相当于 iswblank(c) iswctype(c, wctype("cntrl")) // 相当于 iswcntrl(c) iswctype(c, wctype("digit")) // 相当于 iswdigit(c) iswctype(c, wctype("graph")) // 相当于 iswgraph(c) iswctype(c, wctype("lower")) // 相当于 iswlower(c) iswctype(c, wctype("print")) // 相当于 iswprint(c) iswctype(c, wctype("punct")) // 相当于 iswpunct(c) iswctype(c, wctype("space")) // 相当于 iswspace(c) iswctype(c, wctype("upper")) // 相当于 iswupper(c) iswctype(c, wctype("xdigit")) // 相当于 iswxdigit(c)大小写转换函数wctype.h 提供以下宽字符大小写转换函数。towlower() 将大写宽字符转换为小写towupper() 将小写宽字符转换为大写towctrans() 宽字符大小写转换的通用函数wctrans() 大小写转换的辅助函数，配合 towctrans() 使用先看towlower()和towupper()的用法示例。towlower(L'B') // b towupper(L'e') // Etowctrans()和wctrans()的原型如下。wint_t towctrans(wint_t wc, wctrans_t desc); wctrans_t wctrans(const char* property);下面是它们的用法示例。towctrans(c, wctrans("toupper")) // 相当于 towupper(c) towctrans(c, wctrans("tolower")) // 相当于 towlower(c)扫描二维码，在手机上阅读！

wchar.h
type: item
date: 2023-09-20T09:38:20+08:00
description: wchar.h宽字符使用两个或四个字节表示一个字符，导致 C 语言常规的字符处理函数都会失效。wchar.h 定义了许多宽字符专用的处理函数。类型别名和宏wchar.h 定义了一个类型别名 wint_t，表示宽字符对应整数值。wchar.h 还定义了一个宏 WEOF，表示文件结束字符 EOF 的宽字符版。btowc()，wctob()btowc()将单字节字符转换为宽字符，wctob()将宽字符转换为单字节字符。wint_t btowc(int c); int wctob(wint_t c);btowc()返回一个宽字符。如果参数是 EOF，或转换失败，则返回 WEOF。wctob()返回一个单字节字符。如果参数是 WEOF，或者参数宽字符无法对应单个的单字节字符，则返回 EOF。下面是用法示例。wint_t wc = btowc('B'); // 输出宽字符 B wprintf(L"Wide character: %lc\n", wc); unsigned char c = wctob(wc); // 输出单字节字符 B wprintf(L"Single-byte character: %c\n", c);fwide()fwide()用来设置一个字节流是宽字符流，还是多字节字符流。如果使用宽字符专用函数处理字节流，就会默认设置字节流为宽字符流，否则就需要使用fwide()显式设置。int fwide(FILE* stream, int mode);它接受两个参数，第一个参数是文件指针，第二个参数是字节流模式，有三种选择。0：字节流模式保持原样。-1（或其他负值）：设为多字节字符流。1（或其他正值）：设为宽字符流。fwide()的返回值也分成三种情况：如果是宽字符流，返回一个正值；如果是多字节字符流，返回一个负值；如果是普通字符流，返回0。一旦设置了字节流模式，就无法再更改。#include <stdio.h> #include <wchar.h> int main(void) { wprintf(L"Hello world!\n"); int mode = fwide(stdout, 0); wprintf(L"Stream is %ls-oriented\n", mode < 0 ? L"byte" : L"wide"); }上面示例中，wprintf()将字节流隐式设为宽字符模式，所以fwide(stdout, 0)的返回值大于零。宽字符专用函数下面这些函数基本都是 stdio.h 里面的字符处理函数的宽字符版本，必须使用这些函数来操作宽字符。fgetwc() 从宽字符流中获取宽字符，对应 fgetc()。fgetws() 从宽字符流中读取宽字符串，对应 fgets()。fputwc() 将宽字符写入宽字符流，对应 fputc()。fputws() 将宽字符串写入宽字符流，对应 fputs()。fwprintf() 格式化宽输出到宽字符流，对应 fprintf()。fwscanf() 来自宽字符流的格式化宽字符输入，对应 fscanf()。getwchar() 从 stdin 获取一个宽字符，对应 getchar()。getwc() 从 stdin 获取一个宽字符，对应 getc()。putwchar() 写一个宽字符到 stdout，对应 putchar()。putwc() 写一个宽字符到 stdout，对应 putc()。swprintf() 格式化宽输出到宽字符串，对应 sprintf()。swscanf() 来自宽字符串的格式化宽输入，对应 sscanf()。ungetwc() 将宽字符推回输入流，对应 ungetc()。vfwprintf() 可变参数的格式化宽字符输出到宽字符流，对应 vfprintf()。vfwscanf() 来自宽字符流的可变参数格式化宽字符输入，对应 vfscanf()。vswprintf() 可变参数的格式化宽字符输出到宽字符串，对应 vswprintf()。vswscanf() 来自宽字符串的可变参数格式化宽字符输入，对应 vsscanf()。vwprintf() 可变参数格式化宽字符输出，对应 vprintf()。vwscanf() 可变参数的格式化宽字符输入，对应 vscanf()。wcscat() 危险地连接宽字符串，对应 strcat()。wcschr() 在宽字符串中查找宽字符，对应 strchr()。wcscmp() 比较宽字符串，对应 strcmp()。wcscoll() 比较两个考虑语言环境的宽字符串，对应 strcoll()。wcscpy() 危险地复制宽字符串，对应 strcpy()。wcscspn() 不是从宽字符串前面开始计算字符，对应 strcspn()。w…

time.h
type: item
date: 2023-09-20T09:38:03+08:00
description: time.htime_ttime_t 是一个表示时间的类型别名，可以视为国际标准时 UTC。它可能是浮点数，也可能是整数，Unix 系统一般是整数。许多系统上，time_t 表示自时间纪元（time epoch）以来的秒数。Unix 的时间纪元是国际标准时 UTC 的1970年1月1日的零分零秒。time_t 如果为负数，则表示时间纪元之前的时间。time_t 一般是32位或64位整数类型的别名，具体类型取决于当前系统。如果是32位带符号整数，time_t 可以表示的时间到 2038年1月19日03:14:07 UTC 为止；如果是32位无符号整数，则表示到2106年。如果是64位带符号整数，可以表示-2930亿年到+2930亿年的时间范围。struct tmstruct tm 是一个数据结构，用来保存时间的各个组成部分，比如小时、分钟、秒、日、月、年等。下面是它的结构。struct tm { int tm_sec; // 秒数 [0, 60] int tm_min; // 分钟 [0, 59] int tm_hour; // 小时 [0, 23] int tm_mday; // 月份的天数 [1, 31] int tm_mon; // 月份 [0, 11]，一月用 0 表示 int tm_year; // 距离 1900 的年数 int tm_wday; // 星期几 [0, 6]，星期天用 0 表示 int tm_yday; // 距离1月1日的天数 [0, 365] int tm_isdst; // 是否采用夏令时，1 表示采用，0 表示未采用 };time()time()函数返回从时间纪元到现在经过的秒数。time_t time(time_t* returned_value);time()接受一个 time_t 指针作为参数，返回值会写入指针地址。参数可以是空指针 NULL。time()的返回值是 time_t 类型的当前时间。 如果计算机无法提供当前的秒数，或者返回值太大，无法用time_t类型表示，time()函数就返回-1。time_t now; // 写法一 now = time(NULL); // 写法二 time(&now);上面示例展示了将当前时间存入变量now的两种写法。如果要知道某个操作耗费的精确时间，需要调用两次time()，再将两次的返回值相减。time_t begin = time(NULL); // ... 执行某些操作 time_t end = time(NULL); printf("%d\n", end - begin);注意，上面的方法只能精确到秒。ctime()ctime()用来将 time_t 类型的值直接输出为人类可读的格式。char* ctime( time_t const * time_value );ctime()的参数是一个 time_t 指针，返回一个字符串指针。该字符串的格式类似“Sun Jul 4 04:02:48 1976\n\0”，尾部包含换行符和字符串终止标志。下面是一个例子。time_t now; now = time(NULL); // 输出 Sun Feb 28 18:47:25 2021 printf("%s", ctime(&now));注意，ctime()会在字符串尾部自动添加换行符。localtime()，gmtime()localtime()函数用来将 time_t 类型的时间，转换为当前时区的 struct tm 结构。gmtime()函数用来将 time_t 类型的时间，转换为 UTC 时间的 struct tm 结构。它们的区别就是返回值，前者是本地时间，后者是 UTC 时间。struct tm* localtime(const time_t* timer); struct tm* gmtime(const time_t* timer);下面是一个例子。time_t now = time(NULL); // 输出 Local: Sun Feb 28 20:15:27 2021 printf("Local: %s", asctime(localtime(&now))); // 输出 UTC : Mon Mar 1 04:15:27 2021 printf("UTC : %s", asctime(gmtime(&now)));asctime()asctime()函数用来将 struct tm 结构，直接输出为人类可读的格式。该函数会自动在输出的尾部添加换行符。用法示例参考上一小节。mktime()mktime()函数用于把一个 struct tm 结构转换为 time_t 值。time_t mktime(struct tm* tm_ptr);m…

string.h
type: item
date: 2023-09-20T09:37:43+08:00
description: string.hstring.h主要定义了字符串处理函数和内存操作函数。字符串处理函数以下字符串处理函数，详见《字符串》一章。strcpy()：复制字符串。strncpy()：复制字符串，有长度限制。strcat()：连接两个字符串。strncat()：连接两个字符串，有长度限制。strcmp()：比较两个字符串。strncmp()：比较两个字符串，有长度限制。strlen()：返回字符串的字节数。strchr()，strrchr()strchr()和strrchr()都用于在字符串中查找指定字符。不同之处是，strchr()从字符串开头开始查找，strrchr()从字符串结尾开始查找，函数名里面多出来的那个r表示 reverse（反向）。char* strchr(char* str, int c); char* strrchr(char *str, int c);它们都接受两个参数，第一个参数是字符串指针，第二个参数是所要查找的字符。一旦找到该字符，它们就会停止查找，并返回指向该字符的指针。如果没有找到，则返回 NULL。下面是一个例子。char *str = "Hello, world!"; char *p; p = strchr(str, ','); // p 指向逗号的位置 p = strrchr(str, 'o'); // p 指向 world 里面 o 的位置strspn()，strcspn()strspn()用来查找属于指定字符集的字符串长度，strcspn()正好相反，用来查找不属于指定字符集的字符串长度。size_t strspn(char* str, const char* accept); size_t strcspn(char *str, const char *reject);这两个函数接受两个参数，第一个参数是源字符串，第二个参数是由指定字符组成的字符串。strspn()从第一个参数的开头开始查找，一旦发现第一个不属于指定字符集范围的字符，就停止查找，返回到目前为止的字符串长度。如果始终没有不在指定字符集的字符，则返回第一个参数字符串的长度。strcspn()则是一旦发现第一个属于指定字符集范围的字符，就停止查找，返回到目前为止的字符串长度。如果始终没有发现指定字符集的字符，则返回第一个参数字符串的长度。char str[] = "hello world"; int n; n = strspn(str1, "aeiou"); printf("%d\n", n); // n == 0 n = strcspn(str1, "aeiou"); printf("%d\n", n); // n == 1上面示例中，第一个n等于0，因为0号位置的字符h就不属于指定字符集aeiou，可以理解为开头有0个字符属于指定字符集。第二个n等于1，因为1号位置的字符e属于指定字符集aeiou，可以理解为开头有1个字符不属于指定字符集。strpbrk()strpbrk()在字符串中搜索指定字符集的任一个字符。char* strpbrk(const char* s1, const char* s2);它接受两个参数，第一个参数是源字符串，第二个参数是由指定字符组成的字符串。它返回一个指向第一个匹配字符的指针，如果未找到匹配字符，则返回 NULL。char* s1 = "Hello, world!"; char* s2 = "dow!"; char* p = strpbrk(s1, s2); printf("%s\n", p); // "o, world!"上面示例中，指定字符集是“dow!”，那么s1里面第一个匹配字符是“Hello”的“o”，所以指针p指向这个字符。输出的话，就会输出从这个字符直到字符串末尾的“o, world!”。strstr()strstr()在一个字符串里面，查找另一个字符串。char *strstr( const char* str, const char* substr );它接受两个参数，第一个参数是源字符串，第二个参数是所要查找的子字符串。如果匹配成功，就返回一个指针，指向源字符串里面的子字符串。如果匹配失败，就返回 NULL，表示无法找到子字符串。char* str = "The quick brown fox jumped over the lazy dogs."; char* p = strstr(str, "lazy"); printf("%s\n", p == NULL ? "null": p); // "lazy dogs."上面示例中，strstr()用来在源字符串str里面，查找子字符串lazy。从返回的指针到字符串结尾，就是“lazy dogs.”。strtok()strtok…

stdlib.h
type: item
date: 2023-09-20T09:37:20+08:00
description: stdlib.h类型别名和宏stdlib.h 定义了下面的类型别名。size_t：sizeof 的返回类型。wchar_t：宽字符类型。stdlib.h 定义了下面的宏。NULL：空指针。EXIT_SUCCESS：函数运行成功时的退出状态。EXIT_FAILURE：函数运行错误时的退出状态。RAND_MAX：rand() 函数可以返回的最大值。MB_CUR_MAX：当前语言环境中，多字节字符占用的最大字节数。abs()，labs()，llabs()这三个函数用于计算整数的绝对值。abs()用于 int 类型，labs()用于 long int 类型，llabs()用于 long long int 类型。int abs(int j); long int labs(long int j); long long int llabs(long long int j);下面是用法示例。// 输出 |-2| = 2 printf("|-2| = %d\n", abs(-2)); // 输出 |4| = 4 printf("|4| = %d\n", abs(4));div()，ldiv()，lldiv()这三个函数用来计算两个参数的商和余数。div()用于 int 类型的相除，ldiv()用于 long int 类型的相除，lldiv()用于 long long int 类型的相除。div_t div(int numer, int denom); ldiv_t ldiv(long int numer, long int denom); lldiv_t lldiv(long long int numer, long long int denom);这些函数把第2个参数（分母）除以第1个参数（分子），产生商和余数。这两个值通过一个数据结构返回，div()返回 div_t 结构，ldiv()返回 ldiv_t 结构，lldiv()返回 lldiv_t 结构。这些结构都包含下面两个字段，int quot; // 商 int rem; // 余数它们完整的定义如下。typedef struct { int quot, rem; } div_t; typedef struct { long int quot, rem; } ldiv_t; typedef struct { long long int quot, rem; } lldiv_t;下面是一个例子。div_t d = div(64, -7); // 输出 64 / -7 = -9 printf("64 / -7 = %d\n", d.quot); // 输出 64 % -7 = 1 printf("64 %% -7 = %d\n", d.rem);字符串转成数值a 系列函数stdlib.h定义了一系列函数，可以将字符串转为数字。atoi()：字符串转成 int 类型。atof()：字符串转成 double 类型。atol()：字符串转成 long int 类型。atoll()：字符串转成 long long int 类型。它们的原型如下。int atoi(const char* nptr); double atof(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr);上面函数的参数都是一个字符串指针，字符串开头的空格会被忽略，转换到第一个无效字符处停止。函数名称里面的a代表 ASCII，所以atoi()的意思是“ASCII to int”。它们返回转换后的数值，如果字符串无法转换，则返回0。下面是用法示例。atoi("3490") // 3490 atof("3.141593") // 3.141593如果参数是数字开头的字符串，atoi()会只转换数字部分，比如atoi("42regular")会返回整数42。如果首字符不是数字，比如“hello world”，则会返回0。str 系列函数（浮点数转换）stdlib.h还定义了一些更强功能的浮点数转换函数。strtof()：字符串转成 float 类型。strtod()：字符串转成 double 类型。strtold()：字符串转成 long double 类型。它们的原型如下。float strtof( const char* restrict nptr, char** restrict endptr ); double strtod( const char* restrict nptr, char** restrict endptr ); long double strtold( const char* rest…

stdio.h
type: item
date: 2023-09-20T09:36:58+08:00
description: stdio.hstdio.h是 C 语言的标准 I/O 库，用于读取和写入文件，也用于控制台的输入和输出。标准 I/O 函数以下函数用于控制台的输入和输出。printf()：输出到控制台，详见《基本语法》一章。scanf()：从控制台读取输入，详见《I/O 函数》一章。getchar()：从控制台读取一个字符，详见《I/O 函数》一章。putchar()：向控制台写入一个字符，详见《I/O 函数》一章。gets()：从控制台读取整行输入（已废除），详见《I/O 函数》一章。puts()：向控制台写入一个字符串，详见《I/O 函数》一章。文件操作函数以下函数用于文件操作，详见《文件操作》一章。fopen()：打开文件。fclose()：关闭文件。freopen()：打开一个新文件，关联一个已经打开的文件指针。fprintf()：输出到文件。fscanf()：从文件读取数据。getc()：从文件读取一个字符。fgetc()：从文件读取一个字符。putc()：向文件写入一个字符。fputc()：向文件写入一个字符。fgets()：从文件读取整行。fputs()：向文件写入字符串。fread()：从文件读取二进制数据。fwrite()：向文件写入二进制数据。fseek()：将文件内部指针移到指定位置。ftell()：获取文件内部指针的当前位置。rewind()：将文件内部指针重置到文件开始处。fgetpos()：获取文件内部指针的当前位置。fsetpos()：设置文件内部指针的当前位置。feof()：判断文件内部指针是否指向文件结尾。ferror()：返回文件错误指示器的状态。clearerr()：重置文件错误指示器。remove()：删除文件。rename()：文件改名，以及移动文件。字符串操作函数以下函数用于操作字符串，详见《字符串操作》一章。sscanf()：从字符串读取数据，详见《I/O 函数》一章。sprintf()：输出到字符串。snprintf()：输出到字符串的更安全版本，指定了输出字符串的数量。tmpfile()tmpfile()函数创建一个临时文件，该文件只在程序运行期间存在，除非手动关闭它。它的原型如下。FILE* tmpfile(void);tmpfile()返回一个文件指针，可以用于访问该函数创建的临时文件。如果创建失败，返回一个空指针 NULL。FILE* tempptr; tempptr = tmpfile();调用close()方法关闭临时文件后，该文件将被自动删除。tmpfile()有两个缺点。一是无法知道临时文件的文件名，二是无法让该文件成为永久文件。tmpnam()tmpname()函数为临时文件生成一个名字，确保不会与其他文件重名。它的原型如下。char* tmpname(char* s);它的参数是一个字符串变量，tmpnam()会把临时文件的文件名复制到这个变量里面，并返回指向该字符串变量的指针。如果生成文件名失败，tmpnam()返回空指针 NULL。char filename[L_tmpnam]; if (tmpnam(filename) != NULL) // 输出诸如 /tmp/filew9PMuZ 的文件名 printf("%s\n", filename); else printf("Something wrong!\n");上面示例中，L_tmpnam是stdio.h定义的一个宏，指定了临时文件的文件名长度。tmpname()的参数也可以是一个空指针 NULL，同样返回指向文件名字符串的指针。char* filename; filename = tmpnam(NULL);上面示例中，变量filename就是tmpnam()生成的文件名。该函数只是生成一个文件名，稍后可以使用fopen()打开该文件并使用它。fflush()fflush()用于清空缓存区。它接受一个文件指针作为参数，将缓存区内容写入该文件。fflush(fp);如果不需要保存缓存区内容，则可以传入空指针 NULL。fflush(NULL);如果清空成功，fflush()返回0，否则返回 EOF。注意，fflush()一般只用来清空输出缓存区（比如写文件）。如果使用它来清空输入缓存区（比如读文件），属于未定义行为。fflush()的一个用途是不等回车键，就强迫输出缓存区。大多数系统都是行缓存，这意味着只有遇到回车键（或者缓存区满了，或者文件读到结尾），缓存区的内容才会输出，fflush()可以不等回车键，立即输出。for (int i = 9; i >= 0; i--) { printf("\r%d", i); fflush(stdout); sleep(1); }上面示例是一个倒计时效果，\r是回车键，表示每轮循环…

stdint.h
type: item
date: 2023-09-20T09:36:30+08:00
description: stdint.h固定宽度的整数类型stdint.h 定义了一些固定宽度的整数类型别名，主要有下面三类。宽度完全确定的整数intN_t，比如int32_t。宽度不小于某个大小的整数int_leastN_t，比如int_least8_t。宽度不小于某个大小、并且处理速度尽可能快的整数int_fastN_t，比如int_fast64_t。上面所有类型都是有符号的，类型名前面可以加一个前缀u，表示无符号类型，比如uint16_t。C 语言标准要求定义以下类型。int8_t（可选） uint8_t（可选）int16_t（可选） uint16_t（可选）int32_t（可选） uint32_t（可选）int64_t（可选） uint64_t（可选）int_least8_t uint_least8_tint_least16_t uint_least16_tint_least32_t uint_least32_tint_least64_t uint_least64_tint_fast8_t uint_fast8_tint_fast16_t uint_fast16_tint_fast32_t uint_fast32_tint_fast64_t uint_fast64_t最大宽度的整数类型以下两个类型表示当前系统可用的最大宽度整数。intmax_tuintmax_t如果想要尽可能大的整数时，可以使用上面类型。固定宽度的整数常量以下一些带参数的宏，可以生成固定宽度的整数常量。INT8_C(x) UINT8_C(x)INT16_C(x) UINT16_C(x)INT32_C(x) UINT32_C(x)INT64_C(x) UINT64_C(x)INTMAX_C(x) UINTMAX_C(x)下面是用法示例。uint16_t x = UINT16_C(12); intmax_t y = INTMAX_C(3490);固定宽度的整数极限值下面一些宏代表了固定宽度的整数最大值和最小值。INT8_MAX INT8_MIN UINT8_MAXINT16_MAX INT16_MIN UINT16_MAXINT32_MAX INT32_MIN UINT32_MAXINT64_MAX INT64_MIN UINT64_MAXINT_LEAST8_MAX INT_LEAST8_MIN UINT_LEAST8_MAXINT_LEAST16_MAX INT_LEAST16_MIN UINT_LEAST16_MAXINT_LEAST32_MAX INT_LEAST32_MIN UINT_LEAST32_MAXINT_LEAST64_MAX INT_LEAST64_MIN UINT_LEAST64_MAXINT_FAST8_MAX INT_FAST8_MIN UINT_FAST8_MAXINT_FAST16_MAX INT_FAST16_MIN UINT_FAST16_MAXINT_FAST32_MAX INT_FAST32_MIN UINT_FAST32_MAXINT_FAST64_MAX INT_FAST64_MIN UINT_FAST64_MAXINTMAX_MAX INTMAX_MIN UINTMAX_MAX注意，所有无符号整数类型的最小值都为0，所以没有对应的宏。占位符C 语言还在头文件 inttypes.h 里面，为上面类型定义了printf()和scanf()的占位符，参见《inttypes.h》一章。扫描二维码，在手机上阅读！

stddef.h
type: item
date: 2023-09-20T09:36:14+08:00
description: stddef.hstddef.h提供了常用类型和宏的定义，但没有声明任何函数。这个头文件定义的类型如下。ptrdiff_t：指针相减运算时，返回结果的数据类型。size_t：sizeof运算符返回的类型。wchar_t：一种足够大、能容纳各种字符的类型。以上三个类型都是整数类型，其中ptrdiff_t是有符号整数，size_t是无符号整数。stddef.h定义了两个宏。NULL：空指针。offsetof()offsetof()offsetof()是stddef.h定义的一个宏，用来返回某个属性在 Struct 结构内部的起始位置。由于系统为了字节对齐，可能会在 Struct 结构的属性之间插入空字节，这个宏对于确定某个属性的内存位置很有用。它是一个带参数的宏，接受两个参数。第一个参数是 Struct 结构，第二个参数是该结构的一个属性，返回 Struct 起始位置到该属性之间的字节数。struct s { char a; int b[2]; float c; }; printf("%zu\n", offsetof(struct s, a)); // 0 printf("%zu\n", offsetof(struct s, b)); // 4 printf("%zu\n", offsetof(struct s, c)); // 12对于上面这个 Struct 结构，offsetof(struct s, a)一定等于0，因为a属性是第一个属性，与 Struct 结构自身的地址相同。系统为了字节对齐，在a属性后面分配了3个空字节，导致b属性存储在第4个字节，所以offsetof(struct s, b)和offsetof(struct s, c)分别是4和12。扫描二维码，在手机上阅读！

stdbool.h
type: item
date: 2023-09-20T09:36:00+08:00
description: stdbool.hstdbool.h头文件定义了4个宏。bool：定义为_Bool。true：定义为1。false：定义为0。__bool_true_false_are_defined：定义为1。bool isEven(int number) { if (number % 2) { return true; } else { return false; } }#include <stdio.h> #include <stdbool.h> int main(void) { unsigned long num; unsigned long div; bool isPrime = true; num = 64457; for (div = 2; (div * div) <= num; div++) { if (num % div == 0) isPrime = false; } if (isPrime) { printf("%lu is prime.\n", num); } else { printf("%lu is not prime.\n", num); } return 0; }扫描二维码，在手机上阅读！

stdarg.h
type: item
date: 2023-09-20T09:35:42+08:00
description: stdarg.hstdarg.h定义于函数的可变参数相关的一些方法。va_list 类型va_start()va_arg()：获取当前参数va_end()。va_copy()：it makes a copy of your va_list variable in the exact same state.va_copy() can be useful if you need to scan ahead through the arguments but need to also remember your current place.接受可变函数作为参数的一些方法。vprintf()vfprintf()vsprintf()vsnprintf()#include <stdio.h> #include <stdarg.h> int my_printf(int serial, const char *format, ...) { va_list va; // Do my custom work printf("The serial number is: %d\n", serial); // Then pass the rest off to vprintf() va_start(va, format); int rv = vprintf(format, va); va_end(va); return rv; } int main(void) { int x = 10; float y = 3.2; my_printf(3490, "x is %d, y is %f\n", x, y); }扫描二维码，在手机上阅读！