You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

基于指针的C语言二维数组矩阵乘法程序错误排查求助

问题分析与修正方案

你遇到的矩阵乘法结果错误,主要是因为矩阵乘法的循环逻辑完全搞反,再加上几个内存分配和函数使用的小问题。我们一步步拆解问题并修复:

核心问题1:矩阵乘法的循环维度逻辑错误

矩阵乘法的规则是:若A是n×k矩阵,B是k×m矩阵,结果C是n×m矩阵,每个元素C[i][j] = Σ(A[i][l] * B[l][j]),其中l遍历0到k-1(也就是A的列/B的行这个公共维度)。

但你的prod函数里循环逻辑完全错位:

for (i = 0; i < n; i++)
    for (j = 0; j < k; j++) {  // j遍历的是A的列数k,但结果C的列数应该是m
        sum = 0;
        for (l = 0; l < m; l++)  // l遍历的是m,而非公共维度k
            sum = sum + (x[i][l]*y[l][j]);
        res[i][j] = sum;
    }

正确的逻辑应该是:

  • j遍历m(结果C的列数,对应B的列)
  • l遍历k(公共中间维度,对应A的列/B的行)

核心问题2:prod函数中res未分配内存

你在prod里声明了int **res;,但没有给它分配任何内存就直接赋值res[i][j] = sum,这会触发未定义行为(比如垃圾值、内存访问错误),必须先为res分配n行,每行m个int的空间。

其他次要问题

  1. main中C的内存分配多余:你提前给C分配了内存,但prod会返回新分配的结果矩阵,这会导致原C的内存泄漏,直接接收prod的返回值即可。
  2. read函数的调用冗余:read函数已经通过指针修改了矩阵元素,不需要每次调用都把返回值重新赋值给A/B,直接调用read(A, i, j);就行。
  3. 缺少内存释放:虽然不影响程序运行,但手动分配的内存最好在结束前释放,养成良好习惯。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>

// 读取矩阵指定位置的元素
void read(int **x, int i, int j) {
    printf("Give value to store in cell [%d][%d]: ", i, j);
    scanf("%d", &x[i][j]);
}

// 矩阵乘法:n×k 的x 乘 k×m 的y,返回n×m的结果矩阵
int **prod(int **x, int **y, int n, int m, int k) {
    int i, j, l, sum;
    // 为结果矩阵分配内存
    int **res = (int **)malloc(n * sizeof(int *));
    for (i = 0; i < n; i++) {
        res[i] = (int *)malloc(m * sizeof(int));
    }

    // 正确的矩阵乘法循环逻辑
    for (i = 0; i < n; i++) {          // 遍历结果矩阵的行(对应A的行)
        for (j = 0; j < m; j++) {      // 遍历结果矩阵的列(对应B的列)
            sum = 0;
            for (l = 0; l < k; l++) {  // 遍历公共中间维度(A的列/B的行)
                sum += x[i][l] * y[l][j];
            }
            res[i][j] = sum;
        }
    }
    return res;
}

// 打印指定维度的矩阵
void print(int **x, int r, int c) {
    int i, j;
    printf("\nResult Matrix:\n");
    for (i = 0; i < r; i++) {
        for (j = 0; j < c; j ++) {
            printf("C[%d][%d]: %d\t", i, j, x[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int n, m, k, i, j;
    printf("Give n, m and k: ");
    scanf("%d%d%d", &n, &m, &k);

    int **A, **B, **C;

    // 分配A的内存:n行k列
    A = (int **)malloc(n * sizeof(int *));
    for (i = 0; i < n; i++) {
        A[i] = (int *)malloc(k * sizeof(int));
    }

    // 分配B的内存:k行m列
    B = (int **)malloc(k * sizeof(int *));
    for (i = 0; i < k; i++) {
        B[i] = (int *)malloc(m * sizeof(int));
    }

    // 读取矩阵A的元素
    printf("\nEnter elements of Matrix A (%dx%d):\n", n, k);
    for (i = 0; i < n; i++) {
        for (j = 0; j < k; j++) {
            read(A, i, j);
        }
    }

    // 读取矩阵B的元素
    printf("\nEnter elements of Matrix B (%dx%d):\n", k, m);
    for (i = 0; i < k; i++) {
        for (j = 0; j < m; j++) {
            read(B, i, j);
        }
    }

    // 计算矩阵乘法
    C = prod(A, B, n, m, k);

    // 打印结果
    print(C, n, m);

    // 释放所有分配的内存
    for (i = 0; i < n; i++) free(A[i]);
    free(A);
    for (i = 0; i < k; i++) free(B[i]);
    free(B);
    for (i = 0; i < n; i++) free(C[i]);
    free(C);

    return 0;
}

测试验证

用你给出的测试用例:

  • n=2, m=2, k=2
  • A = [[1,2],[3,4]]
  • B = [[1,2],[3,4]]

运行后会输出预期结果:

Result Matrix:
C[0][0]: 7	C[0][1]: 10	
C[1][0]: 15	C[1][1]: 22	

内容的提问来源于stack exchange,提问作者Foivos Allayiotis

火山引擎 最新活动