
C 语言 stdlib.h 头文件详解
-
- 1、引言
- [2、 头文件概述](#2、 头文件概述)
- [3、 内存分配与释放](#3、 内存分配与释放)
-
- [3.1、 malloc 与 free](#3.1、 malloc 与 free)
- [3.2、 calloc 与 realloc](#3.2、 calloc 与 realloc)
- [4、 字符串与数值转换](#4、 字符串与数值转换)
-
- [4.1、 基础转换示例](#4.1、 基础转换示例)
- [4.2 、strtol 的进阶用法](#4.2 、strtol 的进阶用法)
- [5、 随机数生成](#5、 随机数生成)
-
- [5.1 、生成指定范围的随机数](#5.1 、生成指定范围的随机数)
- [6、 排序与查找](#6、 排序与查找)
-
- [6.1 、qsort 排序](#6.1 、qsort 排序)
- [6.2、 bsearch 二分查找](#6.2、 bsearch 二分查找)
- [7、 程序控制与环境交互](#7、 程序控制与环境交互)
-
- [7.1、 程序终止](#7.1、 程序终止)
- [7.2 、环境变量](#7.2 、环境变量)
- [7.3、 执行系统命令](#7.3、 执行系统命令)
- 8、整数除法与取余
- [9、 常用宏与常量](#9、 常用宏与常量)
- 10、总结
- 二、代码示例

1、引言
在 C 语言的标准库中,<stdlib.h> 是一个极其重要且常用的头文件。它全称是 Standard Library(标准库),提供了内存分配、程序控制、类型转换、随机数生成、排序与查找等一系列基础而强大的功能。无论是初学者还是资深开发者,几乎每个 C 程序都会直接或间接地用到它。
2、 头文件概述
<stdlib.h> 是 C 标准库的一部分,定义了以下内容:
- 类型 :如
size_t、div_t、ldiv_t等。 - 宏 :如
NULL、EXIT_SUCCESS、EXIT_FAILURE、RAND_MAX等。 - 函数:涵盖内存管理、字符串转换、随机数、排序查找、环境交互、程序终止等。
使用该头文件时,只需在源文件顶部包含:
c
#include <stdlib.h>
3、 内存分配与释放
动态内存管理是 <stdlib.h> 最核心的功能之一,主要包含以下四个函数:
| 函数 | 功能 |
|---|---|
malloc(size_t size) |
分配 size 字节的未初始化内存 |
calloc(size_t n, size_t size) |
分配 n 个大小为 size 字节的连续内存,并初始化为 0 |
realloc(void *ptr, size_t size) |
调整已分配内存块的大小 |
free(void *ptr) |
释放之前分配的内存 |
3.1、 malloc 与 free
c
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL) {
fprintf(stderr, "内存分配失败\n");
return EXIT_FAILURE;
}
for (int i = 0; i < 5; i++) {
arr[i] = i * i;
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
return EXIT_SUCCESS;
}
注意事项:
malloc返回void *,使用时通常需要强制类型转换。- 分配失败时返回
NULL,务必检查。 - 使用完毕后必须调用
free释放,否则会造成内存泄漏。
3.2、 calloc 与 realloc
c
#include <stdio.h>
#include <stdlib.h>
int main() {
// calloc:分配并清零
int *p = (int *)calloc(4, sizeof(int));
if (p == NULL) return EXIT_FAILURE;
for (int i = 0; i < 4; i++) {
printf("%d ", p[i]); // 全部为 0
}
printf("\n");
// realloc:扩容到 8 个 int
int *q = (int *)realloc(p, 8 * sizeof(int));
if (q == NULL) {
free(p);
return EXIT_FAILURE;
}
p = q;
p[6] = 42;
printf("p[6] = %d\n", p[6]);
free(p);
return EXIT_SUCCESS;
}
4、 字符串与数值转换
<stdlib.h> 提供了一组将字符串转换为数值的函数:
| 函数 | 功能 |
|---|---|
atoi(const char *str) |
字符串转 int |
atol(const char *str) |
字符串转 long |
atof(const char *str) |
字符串转 double |
strtol(const char *str, char **endptr, int base) |
字符串转 long,支持指定进制 |
strtod(const char *str, char **endptr) |
字符串转 double |
4.1、 基础转换示例
c
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *numStr = "12345";
int num = atoi(numStr);
printf("atoi(\"%s\") = %d\n", numStr, num);
const char *floatStr = "3.14159";
double pi = atof(floatStr);
printf("atof(\"%s\") = %f\n", floatStr, pi);
return EXIT_SUCCESS;
}
4.2 、strtol 的进阶用法
strtol 比 atoi 更安全,因为它能检测转换错误并支持进制:
c
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *hexStr = "FF";
char *endptr;
long value = strtol(hexStr, &endptr, 16);
printf("strtol(\"%s\", base=16) = %ld\n", hexStr, value);
if (*endptr != '\0') {
printf("存在无法转换的字符: %s\n", endptr);
}
return EXIT_SUCCESS;
}
5、 随机数生成
<stdlib.h> 提供了伪随机数生成函数:
| 函数 | 功能 |
|---|---|
rand() |
返回 0 到 RAND_MAX 之间的伪随机整数 |
srand(unsigned int seed) |
设置随机数种子 |
5.1 、生成指定范围的随机数
c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
// 用当前时间作为种子
srand((unsigned int)time(NULL));
// 生成 1 到 100 之间的随机数
for (int i = 0; i < 5; i++) {
int r = rand() % 100 + 1;
printf("%d ", r);
}
printf("\n");
return EXIT_SUCCESS;
}
注意 :rand() % n 会产生轻微偏差,若对均匀性要求极高,可使用更精细的算法。
6、 排序与查找
<stdlib.h> 提供了通用的排序和二分查找函数,它们基于函数指针实现,适用于任意数据类型。
6.1 、qsort 排序
c
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int arr[] = {5, 2, 9, 1, 7};
int n = sizeof(arr) / sizeof(arr[0]);
qsort(arr, n, sizeof(int), compare);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return EXIT_SUCCESS;
}
6.2、 bsearch 二分查找
c
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int arr[] = {1, 3, 5, 7, 9};
int n = sizeof(arr) / sizeof(arr[0]);
int key = 7;
int *found = (int *)bsearch(&key, arr, n, sizeof(int), compare);
if (found != NULL) {
printf("找到元素: %d\n", *found);
} else {
printf("未找到元素\n");
}
return EXIT_SUCCESS;
}
注意 :bsearch 要求数组必须已按升序排序。
7、 程序控制与环境交互
7.1、 程序终止
| 函数 | 功能 |
|---|---|
exit(int status) |
正常终止程序,刷新缓冲区 |
abort() |
异常终止程序,不刷新缓冲区 |
atexit(void (*func)(void)) |
注册程序退出时调用的函数 |
c
#include <stdio.h>
#include <stdlib.h>
void cleanup() {
printf("执行清理操作\n");
}
int main() {
atexit(cleanup);
printf("程序即将退出\n");
return EXIT_SUCCESS;
}
7.2 、环境变量
c
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *path = getenv("PATH");
if (path != NULL) {
printf("PATH = %s\n", path);
} else {
printf("未找到 PATH 环境变量\n");
}
return EXIT_SUCCESS;
}
7.3、 执行系统命令
c
#include <stdlib.h>
int main() {
int ret = system("echo Hello from system()");
return ret;
}
8、整数除法与取余
<stdlib.h> 提供了 div 和 ldiv 函数,一次调用同时返回商和余数:
c
#include <stdio.h>
#include <stdlib.h>
int main() {
div_t result = div(17, 5);
printf("商 = %d, 余数 = %d\n", result.quot, result.rem);
return EXIT_SUCCESS;
}
9、 常用宏与常量
| 宏 | 含义 |
|---|---|
NULL |
空指针常量 |
EXIT_SUCCESS |
程序成功退出码(0) |
EXIT_FAILURE |
程序失败退出码(非 0) |
RAND_MAX |
rand() 能返回的最大值 |
10、总结
<stdlib.h> 是 C 语言标准库中的核心头文件,涵盖了内存管理、类型转换、随机数、排序查找、程序控制等关键功能。熟练掌握这些函数,能够显著提升 C 程序的开发效率与健壮性。
在实际开发中,建议:
- 使用
strtol替代atoi以获得更好的错误检测。 - 动态内存分配后务必检查返回值并及时释放。
- 使用
qsort和bsearch时,确保比较函数逻辑正确。 - 合理使用
atexit注册清理函数,避免资源泄漏。
二、代码示例
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <Windows.h>
// qsort 比较回调函数
int cmp_int(const void* a, const void* b)
{
// 升序排序
return *(const int*)a - *(const int*)b;
}
// bsearch 查找回调函数
int search_cmp(const void* key, const void* elem)
{
return *(const int*)key - *(const int*)elem;
}
// atexit 注册的退出回调
void exit_callback(void)
{
printf("[atexit] 程序即将退出\n");
}
int main(void)
{
SetConsoleOutputCP(CP_UTF8);
// ====================== 1. 内存分配 malloc / calloc / realloc / free ======================
printf("===== 1. 动态内存分配 =====\n");
// malloc:分配原始内存,不初始化
int* p_malloc = (int*)malloc(4 * sizeof(int));
if (p_malloc == NULL)
{
perror("malloc fail");
return -1;
}
p_malloc[0] = 10;
p_malloc[1] = 20;
printf("malloc p_malloc[0] = %d\n", p_malloc[0]);
// calloc:分配内存并全部置0
int* p_calloc = (int*)calloc(4, sizeof(int));
printf("calloc p_calloc[0] = %d\n", p_calloc[0]);
// realloc 重新调整内存大小
int* p_realloc = (int*)realloc(p_malloc, 8 * sizeof(int));
if (p_realloc != NULL)
{
p_malloc = p_realloc;
}
free(p_malloc);
free(p_calloc);
printf("动态内存已释放\n\n");
// ====================== 2. 随机数 rand / srand ======================
printf("===== 2. rand srand 随机数 =====\n");
srand((unsigned int)time(NULL)); // 设置随机种子,只用调用一次
printf("3个随机数: %d, %d, %d\n", rand(), rand(), rand());
// 获取 0~99 随机数
int r = rand() % 100;
printf("0~99随机数:%d\n\n", r);
// ======================3. 字符串转数字 atoi / atol / atof ======================
printf("=====3. atoi atol atof 字符串转数字(简易版)=====\n");
const char* str_int = "1234";
const char* str_long = "123456789";
const char* str_double = "3.1415926";
int i_val = atoi(str_int);
long l_val = atol(str_long);
double d_val = atof(str_double);
printf("atoi: %s -> %d\n", str_int, i_val);
printf("atol: %s -> %ld\n", str_long, l_val);
printf("atof: %s -> %lf\n\n", str_double, d_val);
// ======================4. strtol / strtoul / strtod 安全转换(推荐!) ======================
printf("=====4. strtol strtoul strtod 安全字符串转换 =====\n");
char* endptr;
const char* num_str = "258abc";
long s_l = strtol(num_str, &endptr, 10); //10进制
printf("strtol 转换结果=%ld, 停止位置字符: %s\n", s_l, endptr);
unsigned long s_ul = strtoul("666", NULL, 10);
double s_d = strtod("9.876", NULL);
printf("strtoul=%lu, strtod=%lf\n\n", s_ul, s_d);
// ======================5. abs / labs 绝对值 ======================
printf("=====5. abs labs 绝对值 =====\n");
int a = -100;
long la = -12345678L;
printf("abs(-100)=%d\n", abs(a));
printf("labs(-12345678)=%ld\n\n", labs(la));
// ======================6. qsort 快速排序 ======================
printf("=====6. qsort 快速排序 =====\n");
int arr[] = { 9, 2, 7, 1, 5 };
size_t arr_cnt = sizeof(arr) / sizeof(arr[0]);
qsort(arr, arr_cnt, sizeof(int), cmp_int);
printf("排序后数组:");
for (size_t k = 0;k < arr_cnt;k++)
{
printf("%d ", arr[k]);
}
printf("\n\n");
// ======================7. bsearch 二分查找【数组必须预先有序!】 ======================
printf("=====7. bsearch 二分查找 =====\n");
int key = 7;
int* find_res = (int*)bsearch(&key, arr, arr_cnt, sizeof(int), search_cmp);
if (find_res != NULL)
{
printf("找到数字 %d\n", *find_res);
}
else
{
printf("未找到\n");
}
printf("\n");
// ======================8. atexit 注册退出回调函数 ======================
printf("=====8. atexit 注册退出回调 =====\n");
atexit(exit_callback);
printf("main函数即将执行完毕,atexit回调会在return之前执行\n");
// exit(0); // 强制退出程序,0正常,非0异常,会触发atexit
return 0;
}
运行结果:
c
===== 1. 动态内存分配 =====
malloc p_malloc[0] = 10
calloc p_calloc[0] = 0
动态内存已释放
===== 2. rand srand 随机数 =====
3个随机数: 30528, 14815, 12490
0~99随机数:16
=====3. atoi atol atof 字符串转数字(简易版)=====
atoi: 1234 -> 1234
atol: 123456789 -> 123456789
atof: 3.1415926 -> 3.141593
=====4. strtol strtoul strtod 安全字符串转换 =====
strtol 转换结果=258, 停止位置字符: abc
strtoul=666, strtod=9.876000
=====5. abs labs 绝对值 =====
abs(-100)=100
labs(-12345678)=12345678
=====6. qsort 快速排序 =====
排序后数组:1 2 5 7 9
=====7. bsearch 二分查找 =====
找到数字 7
=====8. atexit 注册退出回调 =====
main函数即将执行完毕,atexit回调会在return之前执行
[atexit] 程序即将退出
d:\user\01417804\桌面\CppProject\cppTest\x64\Debug\cppTest.exe (进程 16504)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用"工具"->"选项"->"调试"->"调试停止时自动关闭控制台"。
按任意键关闭此窗口. . .
