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。