c - C中的矩阵乘法(动态内存分配)
问题描述
我正在尝试在 C 编程中使用动态内存分配执行矩阵乘法,其中我将用户输入用于每个矩阵的行数和列数。当 r1=c2(mat1 r1xc1 and mat2 r2xc2) 但 mat 4x2 和 mat 2x3 给出分段错误时,输出是正确的。好心提醒。
代码如下:
#include<stdio.h>
#include<stdlib.h>
void create(int **arr,int r,int c)
{
int i,j;
for(i=0;i<r;i++)
{
arr[i]=(int*)malloc(sizeof(int)*c);
for(j=0;j<c;j++)
scanf("%d",*(arr+i)+j);
}
}
void display(int **arr,int r,int c)
{
int i,j;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
printf("%d ",*(*(arr+i)+j));
printf("\n");
}
}
void multiply(int **arr1,int **arr2,int **arr3,int r,int c1,int c2)
{
int i,j,k;
for(i=0;i<r;i++)
{
for(j=0;j<c2;j++)
{
arr3[i][j]=0;
for(k=0;k<c1;k++)
*(*(arr3+i)+j) += *(*(arr1+i)+k) * *(*(arr2+k)+j);
}
}
}
int main()
{
int **arr1,r1,c1,**arr2,r2,c2,**arr3;
printf("Enter rows and columns of first matrix: ");
scanf("%d %d",&r1,&c1);
arr1=(int**)malloc(sizeof(int*)*r1*c1);
printf("\nEnter elements of first matrix: ");
create(arr1,r1,c1);
printf("\nThe first matrix is: \n");
display(arr1,r1,c1);
printf("\nEnter rows and columns of second matrix: ");
scanf("%d %d",&r2,&c2);
arr2=(int**)malloc(sizeof(int*)*r2*c2);
printf("\nEnter elements of second matrix: ");
create(arr2,r2,c2);
printf("\nThe second matrix is: \n");
display(arr2,r2,c2);
if(c1!=r2)
{
printf("\nInvalid dimensions.");
exit(0);
}
arr3=(int**)malloc(sizeof(int*)*r1*c2);
printf("\nThe product is: \n");
multiply(arr1,arr2,arr3,r1,c1,c2);
display(arr3,r1,c2);
free(arr1);
free(arr2);
free(arr3);
return 0;
}
解决方案
您遇到分段错误的主要原因是您没有为生成的矩阵arr3分配矩阵行。代码中的其他错误表明您还没有完全理解矩阵的内存组织。
您选择了一个所谓的行优先数组。这是一个可靠的选择。在内存中,它看起来像这样(对于 3 x 4 矩阵):
每一行都是单独分配的(作为一个数字数组)。这些是水平条。
行由垂直条(数组的数组)保持在一起。在 C 中,它基本上是一个指针数组。
最后,您有一个变量来保存对垂直条的引用(在图中称为arr)。它是用来表示矩阵的变量。
现在很明显,每个矩阵需要多个内存分配,一个用于垂直条,多个用于行。竖线在您的main()
函数中分配,行在函数中分配create()
。但create()
不是被要求的arr3
。所以它会导致分段错误。
您的代码中还有其他问题:
- 竖线的内存分配太大了。该数组只需要大小为r,而不需要大小为r * c(r和c是行数和列数)。
- 行的数组永远不会被释放。
我还建议使用数组表示法来访问矩阵元素而不是指针算术。因此,而不是:
*(*(arr1+i)+k)
你可以使用:
arr1[i][k]
它适用于小矩阵的原因是运气。它可能已经覆盖了其他一些数据,这通常会导致崩溃。