C 语言动态数组
外观
动态数组是C语言中通过内存动态分配实现的、可在运行时调整大小的数组结构。与静态数组不同,其内存空间从堆(heap)而非栈(stack)分配,需手动管理内存生命周期。
核心概念[编辑 | 编辑源代码]
静态数组的局限性[编辑 | 编辑源代码]
静态数组在编译时确定大小,无法应对以下场景:
int static_arr[5]; // 大小固定为5
- 数据量未知时可能浪费内存或溢出
- 无法在运行时扩展/收缩
动态数组原理[编辑 | 编辑源代码]
通过指针和内存管理函数实现:
malloc()
:分配内存块calloc()
:分配并清零内存realloc()
:调整已分配内存大小free()
:释放内存
基础实现[编辑 | 编辑源代码]
创建动态数组[编辑 | 编辑源代码]
#include <stdio.h>
#include <stdlib.h>
int main() {
int size = 5;
int *dyn_arr = (int*)malloc(size * sizeof(int));
if (dyn_arr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 初始化数组
for (int i = 0; i < size; i++) {
dyn_arr[i] = i * 10;
}
// 使用示例
printf("动态数组元素:");
for (int i = 0; i < size; i++) {
printf("%d ", dyn_arr[i]);
}
free(dyn_arr); // 必须释放
return 0;
}
输出:
动态数组元素:0 10 20 30 40
调整数组大小[编辑 | 编辑源代码]
使用realloc
时需注意:
- 原指针可能被无效化
- 新内存区域可能迁移到不同地址
int new_size = 10;
int *temp = (int*)realloc(dyn_arr, new_size * sizeof(int));
if (temp == NULL) {
printf("内存重分配失败\n");
free(dyn_arr); // 释放原始内存
return 1;
}
dyn_arr = temp; // 更新指针
高级应用[编辑 | 编辑源代码]
二维动态数组[编辑 | 编辑源代码]
通过指针数组实现:
int rows = 3, cols = 4;
int **matrix = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix[i] = (int*)malloc(cols * sizeof(int));
}
// 释放时需逆向操作
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
动态字符串数组[编辑 | 编辑源代码]
结合字符串特性处理:
char **str_array = (char**)malloc(5 * sizeof(char*));
for (int i = 0; i < 5; i++) {
str_array[i] = (char*)malloc(20 * sizeof(char));
sprintf(str_array[i], "String%d", i+1);
}
内存管理最佳实践[编辑 | 编辑源代码]
1. NULL检查:每次分配后验证指针
2. 初始化内存:calloc
或手动初始化
3. 释放后置空:避免悬垂指针
free(ptr);
ptr = NULL;
4. 匹配释放:每种分配方式对应正确释放
性能考量[编辑 | 编辑源代码]
- 时间复杂度:
realloc
可能触发内存拷贝 - 内存碎片风险:频繁调整大小可能导致碎片
- 预分配策略:根据场景预估初始大小
实际案例[编辑 | 编辑源代码]
动态数据收集器[编辑 | 编辑源代码]
处理未知数量的用户输入:
#include <stdio.h>
#include <stdlib.h>
int main() {
int capacity = 2;
int count = 0;
int *numbers = (int*)malloc(capacity * sizeof(int));
printf("输入整数序列(以-1结束):\n");
while (1) {
int input;
scanf("%d", &input);
if (input == -1) break;
if (count >= capacity) {
capacity *= 2;
numbers = (int*)realloc(numbers, capacity * sizeof(int));
printf("数组扩容至%d\n", capacity);
}
numbers[count++] = input;
}
printf("最终数组:");
for (int i = 0; i < count; i++) {
printf("%d ", numbers[i]);
}
free(numbers);
return 0;
}
示例交互:
输入整数序列(以-1结束): 10 20 30 40 50 -1 数组扩容至4 数组扩容至8 最终数组:10 20 30 40 50
常见错误[编辑 | 编辑源代码]
错误类型 | 示例 | 后果 |
---|---|---|
内存泄漏 | 忘记free |
程序内存持续增长 |
悬垂指针 | 释放后继续使用指针 | 未定义行为 |
缓冲区溢出 | 越界访问 | 数据损坏/安全漏洞 |
双重释放 | 对同一指针多次free |
程序崩溃 |
扩展阅读[编辑 | 编辑源代码]
- 数据结构:动态数组是向量(Vector)的基础实现
- 对比:C++中的
std::vector
提供自动内存管理 - 进阶:内存池技术优化频繁分配场景