C语言中用函数初始化并打印二维数组的问题排查
动态二维数组初始化与打印的问题修复
一、初始化函数返回int**的合理性
完全合理。你实现的是指针数组形式的动态二维数组:int** 表示指向int指针的指针,每个指针指向一行int数组的首地址,这种结构需要用int**来承载,返回这个类型是正确的。
二、代码中的错误与修复
你的代码存在多处内存分配逻辑错误,导致打印函数无法正常运行,具体问题和修复如下:
1. 指针数组的内存分配错误
原代码中计算指针数组大小用了sizeof(n),但matrix是int**类型,每个元素是int*指针,应该用sizeof(int*)计算单个指针的大小:
// 错误写法 matrix = (int**)malloc(n * sizeof(n)); // 修复后 matrix = (int**)malloc(n * sizeof(int*));
2. 行内存分配的循环次数错误
原代码循环次数用了列数m,但需要给n行分配内存,循环条件应改为i < n:
// 错误写法 for (int i = 0; i < m; i++) // 修复后 for (int i = 0; i < n; i++)
3. 每行数组的内存分配错误
原代码计算每行数组大小用了sizeof(m),每行是int类型数组,应该用sizeof(int):
// 错误写法 *(matrix + i) = (int*)malloc(m * sizeof(m)); // 修复后(用数组下标写法更直观) matrix[i] = (int*)malloc(m * sizeof(int));
4. 打印函数的返回值问题
原打印函数声明为int类型,但函数内没有return语句,会触发未定义行为。打印操作不需要返回值,应将返回类型改为void:
// 错误写法 int print_matrix(int n1, int n2, int** a) // 修复后 void print_matrix(int n1, int n2, int** a)
5. 内存泄漏防护(可选但推荐)
如果某一行内存分配失败,需要释放之前已分配的行内存,避免泄漏,可在分配行内存的循环中加入判断逻辑。
三、修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <time.h> int** matrix_initialization(int n, int m) { int** matrix = NULL; // 分配指针数组(行指针) matrix = (int**)malloc(n * sizeof(int*)); if (matrix != NULL) { // 为每一行分配内存,失败时回滚 for (int i = 0; i < n; i++) { matrix[i] = (int*)malloc(m * sizeof(int)); if (matrix[i] == NULL) { for (int j = 0; j < i; j++) { free(matrix[j]); } free(matrix); return NULL; } } // 填充随机值 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { matrix[i][j] = rand() % 20 - 5; } } } return matrix; } void print_matrix(int n1, int n2, int** a) { for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { printf("%d\t", a[i][j]); } printf("\n"); } } int main() { srand(time(NULL)); int N, M, **a; scanf("%d %d", &N, &M); // VS环境可保留scanf_s,其他环境用标准scanf a = matrix_initialization(N, M); if (a != NULL) { print_matrix(N, M, a); // 释放内存,避免泄漏 for (int i = 0; i < N; i++) { free(a[i]); } free(a); } return 0; }
补充说明
- 使用完动态分配的二维数组后,必须逐层释放内存:先释放每一行的int数组,再释放指针数组本身。
- 若使用VS编译器,可保留
scanf_s,其他编译器建议使用标准scanf。
内容的提问来源于stack exchange,提问作者Kr1sp0
相关产品推荐
相关产品推荐

