在C语言中,动态生成二维数组主要有两种常见方法:指针数组和指向指针的指针,以下是详细的实现步骤和示例代码。

(图片来源网络,侵删)
方法1:使用指针数组(行连续存储)
这种方法适合每行长度相同的情况,内存是连续分配的,访问效率较高。
步骤:
- 分配行指针数组:
int **arr = malloc(rows * sizeof(int*)) - 分配每行的内存:循环分配
malloc(cols * sizeof(int)) - 使用数组:通过
arr[i][j]访问元素 - 释放内存:先释放每行,再释放行指针数组
示例代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 4;
int **arr;
// 1. 分配行指针数组
arr = (int **)malloc(rows * sizeof(int *));
if (arr == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 2. 分配每行的内存
for (int i = 0; i < rows; i++) {
arr[i] = (int *)malloc(cols * sizeof(int));
if (arr[i] == NULL) {
perror("内存分配失败");
// 释放已分配的内存
for (int j = 0; j < i; j++) {
free(arr[j]);
}
free(arr);
exit(EXIT_FAILURE);
}
}
// 3. 初始化数组(示例)
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = i * cols + j;
}
}
// 4. 打印数组
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
// 5. 释放内存
for (int i = 0; i < rows; i++) {
free(arr[i]);
}
free(arr);
return 0;
}
方法2:使用单块内存(完全连续存储)
这种方法将整个二维数组分配为一块连续的内存,模拟静态数组的行为,适合需要高效访问的场景。
步骤:
- 分配总内存:
int *arr = malloc(rows * cols * sizeof(int)) - 创建行指针:
int **ptr = malloc(rows * sizeof(int*)),并将每行的起始地址赋值给ptr[i] - 使用数组:通过
ptr[i][j]访问 - 释放内存:先释放行指针,再释放总内存
示例代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 4;
int *arr;
int **ptr;
// 1. 分配总内存
arr = (int *)malloc(rows * cols * sizeof(int));
if (arr == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 2. 分配行指针数组
ptr = (int **)malloc(rows * sizeof(int *));
if (ptr == NULL) {
perror("内存分配失败");
free(arr);
exit(EXIT_FAILURE);
}
// 3. 设置每行的起始地址
for (int i = 0; i < rows; i++) {
ptr[i] = arr + i * cols;
}
// 4. 初始化数组(示例)
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
ptr[i][j] = i * cols + j;
}
}
// 5. 打印数组
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", ptr[i][j]);
}
printf("\n");
}
// 6. 释放内存
free(ptr);
free(arr);
return 0;
}
方法3:使用一维数组模拟二维数组
最简单的方式,直接分配一维数组,通过索引计算访问二维元素。
示例代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 4;
int *arr = malloc(rows * cols * sizeof(int));
if (arr == NULL) {
perror("内存分配失败");
exit(EXIT_FAILURE);
}
// 初始化
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i * cols + j] = i * cols + j;
}
}
// 打印
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i * cols + j]);
}
printf("\n");
}
free(arr);
return 0;
}
-
内存连续性:
(图片来源网络,侵删)- 方法1(指针数组)的行是连续的,但整体不连续。
- 方法2(单块内存)完全连续,访问效率最高。
- 方法3(一维数组)完全连续,但需要手动计算索引。
-
释放顺序:
必须先释放子块(每行),再释放父块(行指针)。
-
错误处理:
- 每次分配后检查
malloc是否返回NULL,避免内存泄漏。
- 每次分配后检查
-
适用场景:
- 需要动态调整行数时,方法1更灵活。
- 需要高效访问时,方法2或方法3更优。
根据实际需求选择合适的方法!
