C 标准库总览表
下表按功能类别列出了常用头文件。您可根据需求先在表中找到相应功能与头文件,再查看后续的示例与注意事项。
| 功能类别 | 头文件 | 主要功能/特性 | 常用函数例子 |
|---|---|---|---|
| 标准输入输出(I/O) | <stdio.h> | 标准输入输出、文件操作 | printf(), scanf(), fopen(), fgets(), fprintf() |
| 内存与工具函数 | <stdlib.h> | 内存分配、程序退出、转换函数、随机数 | malloc(), free(), exit(), atoi(), strtol(), rand() |
| 字符串与内存操作 | <string.h> | 字符串处理、内存块操作 | strlen(), strcpy(), strncpy(), strcat(), memcmp() |
| 字符分类与转换 | <ctype.h> | 字符分类检查与大小写转换 | isalpha(), isdigit(), isspace(), toupper(), tolower() |
| 时间与日期 | <time.h> | 获取系统时间、格式化日期时间、计时 | time(), localtime(), gmtime(), strftime(), clock() |
| 数学函数 | <math.h> | 基本数学运算与函数 | sin(), cos(), tan(), log(), sqrt(), pow() |
| 错误处理与断言 | <errno.h>, <assert.h> | 错误码 errno 与断言调试辅助 | assert(), perror(), strerror() |
| 类型限制与定长整数 | <limits.h>, <float.h>, <stdint.h>, <inttypes.h> | 基本类型范围、浮点限制、定长整数类型及格式化宏 | INT_MAX, DBL_MAX, int32_t, PRId32 |
| 布尔类型支持 | <stdbool.h> | 布尔类型 bool, true, false | (无函数,仅宏与类型定义) |
| 本地化与宽字符支持 | <locale.h>, <wchar.h>, <wctype.h>, <uchar.h> | 地域化设置、宽字符与Unicode支持 | setlocale(), wprintf(), iswalpha() |
| 信号与非局部跳转 | <signal.h>, <setjmp.h> | 信号处理与非局部跳转 | signal(), raise(), setjmp(), longjmp() |
| 可变参数处理 | <stdarg.h> | 可变参数函数支持(如实现printf风格函数) | va_list, va_start(), va_arg(), va_end() |
| 原子与多线程(C11) | <stdatomic.h>, <threads.h> | 原子操作、多线程API(C11引入) | atomic_store(), thrd_create(), thrd_join(), mtx_lock() |
| 对齐与不可返回函数(C11) | <stdalign.h>, <stdnoreturn.h> | 内存对齐与不可返回函数说明 | alignof(), _Noreturn关键字 |
| 复数与特殊数学(C99) | <complex.h>, <fenv.h>, <tgmath.h> | 复数操作、浮点环境控制、类型泛型数学宏 | cabs(), fesetround(), 使用tgm宏自动选择数学函数版本 |
深入示例与注意事项
1. 标准输入输出(<stdio.h>)
典型场景:文件读写、标准输入输出、格式化打印。
示例:将文本写入文件并读出
#include <stdio.h>
#include <stdlib.h>int main() {FILE *fp = fopen("data.txt", "w");if (!fp) {perror("Open for writing failed");return EXIT_FAILURE;}fprintf(fp, "Hello, world!\n");fclose(fp);fp = fopen("data.txt", "r");if (!fp) {perror("Open for reading failed");return EXIT_FAILURE;}char buf[100];if (fgets(buf, sizeof(buf), fp)) {printf("Read: %s", buf);}fclose(fp);return 0;
}
注意事项:
- 使用
fgets()而非gets()来避免缓冲区溢出。 - 打开文件后需记得
fclose()。 - 格式化输出时,确保格式说明符匹配传入参数类型。
2. 内存分配与通用工具(<stdlib.h>)
典型场景:动态分配数组,转换字符串为数值,生成随机数。
示例:动态分配与随机数
#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main() {int *arr = malloc(5 * sizeof(int));if (!arr) {fprintf(stderr, "malloc failed\n");return EXIT_FAILURE;}for (int i = 0; i < 5; i++) arr[i] = i*i;srand((unsigned)time(NULL));int r = rand() % 100;printf("Random: %d\n", r);free(arr);return 0;
}
注意事项:
- 每次
malloc()/calloc()分配的内存必须free()。 - 对转换类函数如
atoi(),若需严谨错误检测,用strtol()替代。
3. 字符串与内存(<string.h>)
典型场景:字符串复制、拼接、比较,内存块拷贝清零。
示例:安全字符串拷贝与搜索
#include <stdio.h>
#include <string.h>int main() {char src[] = "Hello C";char dest[20];// 使用strncpy以避免溢出,并手动添加'\0'strncpy(dest, src, sizeof(dest)-1);dest[sizeof(dest)-1] = '\0';printf("Copied: %s\n", dest);char *pos = strstr(dest, "C");if (pos) {printf("Found 'C' at index %ld\n", pos - dest);}return 0;
}
注意事项:
- 始终确保目标缓冲区足够大,并在需要时手动添加终止符
'\0'。 - 对二进制数据用
memcpy()/memmove()而非strcpy()。
4. 字符类型检查(<ctype.h>)
典型场景:判断字符是否字母、数字,转换大小写。
示例:
#include <stdio.h>
#include <ctype.h>int main() {char c = '9';if (isdigit((unsigned char)c)) {printf("%c is a digit\n", c);}c = 'a';printf("Uppercase: %c\n", toupper((unsigned char)c));return 0;
}
注意事项:
- 将
char转为unsigned char传给isxxx()函数,以避免负值出现未定义行为。
5. 时间与日期(<time.h>)
典型场景:获取当前时间、格式化输出、统计运行时间。
示例:打印当前时间
#include <stdio.h>
#include <time.h>int main() {time_t now = time(NULL);struct tm *lt = localtime(&now);char buf[100];strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt);printf("Local time: %s\n", buf);return 0;
}
注意事项:
localtime()返回静态存储区指针,下次调用会覆盖,使用前若需保存结果请复制数据。- C标准不提供复杂日期处理,需要自行处理闰年等逻辑或使用第三方库。
6. 数学函数(<math.h>)
典型场景:计算三角函数、对数、指数、开方、幂。
示例:计算圆面积
#include <stdio.h>
#include <math.h>int main() {double radius = 2.0;double area = M_PI * pow(radius, 2);printf("Area: %f\n", area);return 0;
}
注意事项:
- 确保定义
_USE_MATH_DEFINES(在某些编译器中)或自己定义PI来使用M_PI。 - 浮点精度有限,比较时需考虑误差。
7. 错误处理与断言(<errno.h>, <assert.h>)
典型场景:检查函数调用失败原因,调试时检查不变条件。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>int main() {FILE *fp = fopen("nonexist.txt", "r");if (!fp) {fprintf(stderr, "Error: %s\n", strerror(errno));}int x = 10;assert(x == 10); // 若不满足则程序中断return 0;
}
注意事项:
- 发布版本可
#define NDEBUG禁用assert()。 errno只在特定函数失败时有意义。
8. 类型限制与定长整数
典型场景:确定整数范围、使用定长类型确保跨平台一致性。
示例:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <limits.h>int main() {printf("INT_MAX = %d\n", INT_MAX);int32_t val = 12345;printf("val = %" PRId32 "\n", val);return 0;
}
注意事项:
- 使用
<stdint.h>确保整数位宽固定。 <inttypes.h>提供打印定长整数的安全格式化宏。
9. 布尔与本地化支持(<stdbool.h>, <locale.h>等)
典型场景:使用布尔类型代码更清晰,或设置地域化格式。
示例(布尔类型):
#include <stdio.h>
#include <stdbool.h>int main() {bool flag = true;if (flag) {printf("Flag is true\n");}return 0;
}
示例(locale):
#include <stdio.h>
#include <locale.h>int main() {setlocale(LC_ALL, "");// 输出可能在特定语言环境下启用特殊格式printf("%'.2f\n", 1234567.89); return 0;
}
注意事项:
- 地域化支持依赖系统环境,
setlocale()设置地区后相关函数的行为(如数字分组符)才会改变。 <wchar.h>、<wctype.h>用于宽字符处理,多语言字符需使用Unicode知识。
10. 信号处理与非局部跳转(<signal.h>, <setjmp.h>)
典型场景:捕捉Ctrl+C中断或在深层函数中发生错误时跳回上层函数。
示例(signal):
#include <stdio.h>
#include <signal.h>void handler(int sig) {printf("Caught signal %d\n", sig);
}int main() {signal(SIGINT, handler);while (1) {// 按 Ctrl+C 看效果}return 0;
}
注意事项:
- 信号处理函数中只能调用异步信号安全函数。
- 非局部跳转
setjmp()和longjmp()不推荐滥用,影响代码可读性和可维护性。
11. 可变参数(<stdarg.h>)
典型场景:实现自定义变参函数,比如日志函数。
示例:
#include <stdio.h>
#include <stdarg.h>void print_numbers(int count, ...) {va_list args;va_start(args, count);for (int i = 0; i < count; i++) {int num = va_arg(args, int);printf("%d ", num);}va_end(args);printf("\n");
}int main() {print_numbers(3, 10, 20, 30);return 0;
}
注意事项:
- 需约定参数类型顺序,无类型安全检查。
- 如果能固定参数数量或使用变参安全框架更好。
12. 原子与多线程(C11)(<stdatomic.h>, <threads.h>)
典型场景:使用标准原子操作、跨平台基础多线程。
示例(简单线程):
#include <stdio.h>
#include <threads.h>int func(void *arg) {printf("In thread: %d\n", *(int*)arg);return 0;
}int main() {int val = 42;thrd_t t;if (thrd_create(&t, func, &val) == thrd_success) {thrd_join(t, NULL);}return 0;
}
注意事项:
- 功能不如Java
Thread和并发库丰富。仅适合简单多线程场景。 <stdatomic.h>提供类似C++原子操作功能,保证数据访问的原子性。
13. 对齐与不可返回函数(C11)
典型场景:特殊场景下需指定类型对齐或标识函数不返回。
示例:
#include <stdalign.h>
#include <stdnoreturn.h>
#include <stdio.h>
#include <stdlib.h>_Noreturn void fail(const char *msg) {fprintf(stderr, "%s\n", msg);exit(EXIT_FAILURE);
}int main() {struct {alignas(16) int x; } s;s.x = 10;// fail("This function never returns");return 0;
}
注意事项:
- 大部分日常开发无需显式使用对齐特性。
_Noreturn函数不能返回,否则未定义行为。
14. 复数与特殊数学(C99)(<complex.h>, <fenv.h>, <tgmath.h>)
典型场景:科学计算,处理复数或控制浮点环境(如舍入方式)。
示例(复数):
#include <stdio.h>
#include <complex.h>
#include <math.h>int main() {double complex z = 1.0 + 2.0*I;double r = cabs(z);printf("|1+2i| = %f\n", r);return 0;
}
注意事项:
- 日常通用开发中很少使用。
<fenv.h>控制浮点异常、舍入等,需要特殊场景。
总结与建议
- 安全性与内存管理:C无自动内存管理和越界检查,需格外小心。
- 错误处理:充分利用
errno、perror(), 并在调试期使用assert()确保逻辑正确。 - 国际化与复杂场景:对于多语言文本、时区、本地化格式等,高级功能需
<locale.h>、<wchar.h>、<wctype.h>支持,且平台相关性更高。 - 扩展与第三方库:C标准库提供基础功能,如需高级数据结构、网络编程、图形界面等,需第三方库或操作系统API。
