C语言双指针传参实现矩阵乘法出现段错误的问题求助
问题分析与修复
核心问题1:二维数组与int**的类型不匹配
你在main里定义的是变长二维数组(VLA),比如int matrixA[M][N],它在内存中是连续存储的一块区域,当它退化为指针时,类型是int (*)[N](指向包含N个int的数组的指针),而不是int**。
你强制把matrixA转成int**传给multiply函数后,函数里执行*(matrixA + j)时,会把matrixA起始地址处的4/8字节(int的大小)当成一个指针地址去访问——但这其实是数组里的第一个元素值,不是合法指针,直接触发段错误。
核心问题2:矩阵乘法的索引逻辑错误
你的三重循环里,矩阵乘法的元素索引写错了:
正确的矩阵乘法应该是matrixC[i][j] = sum(matrixA[i][k] * matrixB[k][j]),但你写成了matrixA[j][k] * matrixB[k][j],这会导致计算结果完全错误,即使没有段错误也得不到正确结果。
修复方案(两种可选)
方案1:直接使用变长数组(VLA)作为函数参数
这是最贴合你现有代码的方案,不需要修改数组定义,只需要调整函数参数类型:
// 修改函数参数为VLA类型 void multiply(int M, int N, int K, int matrixA[M][N], int matrixB[N][K], int matrixC[M][K]){ for (int i = 0; i < M; i++){ for (int j = 0; j < K; j++){ int sum = 0; for (int k = 0; k < N; k++){ // 修正索引逻辑 sum += matrixA[i][k] * matrixB[k][j]; } matrixC[i][j] = sum; } } } int main(){ int M, N, K; scanf("%d%d%d", &M, &N, &K); int matrixA[M][N]; int matrixB[N][K]; int matrixC[M][K]; // 输入矩阵A for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ scanf("%d", &matrixA[i][j]); // 改成&更直观,原写法也合法但可读性差 } } // 输入矩阵B for(int i=0; i<N; i++){ for(int j=0; j<K; j++){ scanf("%d", &matrixB[i][j]); } } // 直接传递数组,无需强制类型转换 multiply(M, N, K, matrixA, matrixB, matrixC); // 输出结果 for(int i=0; i<M; i++){ for(int j=0; j<K; j++){ printf("%d ", matrixC[i][j]); } printf("\n"); } return 0; }
方案2:使用动态分配的int**二维数组
如果需要更灵活的内存管理(比如数组大小在运行时动态调整且不想用VLA),可以手动分配指针数组和每行的内存:
#include <stdlib.h> // 需要malloc/free void multiply(int M, int N, int K, int **matrixA, int **matrixB, int **matrixC){ for (int i = 0; i < M; i++){ for (int j = 0; j < K; j++){ int sum = 0; for (int k = 0; k < N; k++){ sum += matrixA[i][k] * matrixB[k][j]; } matrixC[i][j] = sum; } } } int main(){ int M, N, K; scanf("%d%d%d", &M, &N, &K); // 动态分配matrixA int **matrixA = malloc(M * sizeof(int*)); for(int i=0; i<M; i++){ matrixA[i] = malloc(N * sizeof(int)); } // 动态分配matrixB int **matrixB = malloc(N * sizeof(int*)); for(int i=0; i<N; i++){ matrixB[i] = malloc(K * sizeof(int)); } // 动态分配matrixC int **matrixC = malloc(M * sizeof(int*)); for(int i=0; i<M; i++){ matrixC[i] = malloc(K * sizeof(int)); } // 输入矩阵A for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ scanf("%d", &matrixA[i][j]); } } // 输入矩阵B for(int i=0; i<N; i++){ for(int j=0; j<K; j++){ scanf("%d", &matrixB[i][j]); } } multiply(M, N, K, matrixA, matrixB, matrixC); // 输出结果 for(int i=0; i<M; i++){ for(int j=0; j<K; j++){ printf("%d ", matrixC[i][j]); } printf("\n"); } // 释放内存,避免泄漏 for(int i=0; i<M; i++) free(matrixA[i]); free(matrixA); for(int i=0; i<N; i++) free(matrixB[i]); free(matrixB); for(int i=0; i<M; i++) free(matrixC[i]); free(matrixC); return 0; }
关键知识点总结
- 栈上的二维数组(包括VLA)和动态分配的
int**二维数组是完全不同的内存结构,不能强制转换混用。 - 矩阵乘法的三重循环索引顺序要对应:
C[i][j]是A的第i行和B的第j列对应元素相乘求和。
内容的提问来源于stack exchange,提问作者ArasChang
相关产品推荐
相关产品推荐

