Reputation: 115
I am trying to code for matrix multiplication of square matrices and it will keep giving Segmentation fault after every few entires on several trials. I looked up different question on the site and tried few ways around with two following codes.
Also, Why do we need the pointers to "pointer to a pointer" as given by int **mat1, **mat2 etc. ? I don't know why this is to be done but I saw it in some answer itself.
Code 1
void mxmult()
{
int n,m,a,b,c,d, sum=0;
int x,y,z;
printf("Enter first order [n*n]\n");
scanf("%d", &n);
printf("Enter second order [m*m]\n");
scanf("%d", &m);
if (n!=m)
{
printf("Invalid orders");
}
else
{
//mem allocate for matrix 1
int **mat1 = (int**)malloc(n*sizeof(int));
for(x=0;x<n;x++)
{
mat1[x]=(int*)malloc(n*sizeof(int));
}
// input matrix 1
printf("Enter the first matrix entries\n");
for (a = 0; a <n; a++)
{
for (b = 0; b < n; b++)
{
scanf("%d", &mat1[a][b]);
}
}
// memory allocate matrix 2
int **mat2 = (int**)malloc(m*sizeof(int));
for(y=0;y<n;y++)
{
mat2[y]=(int*)malloc(m*sizeof(int));
}
//inpur matrix 2
printf("Enter the second matrix entries\n");
for (c = 0; c <n; c++)
{
for (d= 0; d < n; d++)
{
scanf("%d", &mat2[c][d]);
}
}
//Memory allocate matrix Mult
int **mult=(int**)malloc(m*sizeof(int));
for(z=0;z<m;z++)
mult[z]=(int*)malloc(m*sizeof(int));
for (a = 0; a < n; a++)
{
for (d = 0; d < m; d++)
{
for (c = 0; c < n; c++)
{
sum=sum + (mat1[a][c] *mat2[c][d]);
}
mult[a][d] = sum;
sum= 0;
}
}
printf("Product\n");
for ( a = 0 ; a < n ; a++ )
{
for ( d = 0 ; d < m ; d++)
printf("%d\t", mult[a][d]);
printf("\n");
}
}
}
Code 2:
void mxmult()
{
int n,m,a,b,c,d, sum=0;
int x,y,z;
printf("Enter first order [n*n]\n");
scanf("%d", &n);
printf("Enter second order [m*m]\n");
scanf("%d", &m);
if (n!=m)
{
printf("Invalid orders");
}
else
{
//mem allocate for matrix 1
int **mat1 = (int**)malloc(n*n*sizeof(int));
// input matrix 1
printf("Enter the first matrix entries\n");
for (a = 0; a <n; a++)
{
for (b = 0; b < n; b++)
{
scanf("%d", &mat1[a][b]);
}
}
// memory allocate matrix 2
int **mat2 = (int**)malloc(m*m*sizeof(int));
//input matrix 2
printf("Enter the second matrix entries\n");
for (c = 0; c <n; c++)
{
for (d= 0; d < n; d++)
{
scanf("%d", &mat2[c][d]);
}
}
//Memory allocate matrix Mult
int **mult=(int**)malloc(m*m*sizeof(int));
// Mx multiplicatn
for (a = 0; a < n; a++)
{
for (d = 0; d < m; d++)
{
for (c = 0; c < n; c++)
{
sum=sum + (mat1[a][c] *mat2[c][d]);
}
mult[a][d] = sum;
sum= 0;
}
}
printf("Product\n");
for ( a = 0 ; a < n ; a++ )
{
for ( d = 0 ; d < m ; d++)
printf("%d\t", mult[a][d]);
printf("\n");
}
}
}
I have been trying to execute code 2 and then, code2 . Both end up giving seg faults after few entires.
Upvotes: 2
Views: 10582
Reputation: 33019
The int **
type is what is called a ragged array. You create a ragged array by first allocating a "spine" array, which contains pointers to each of the "ribs". When you reference matrix[x][y]
, you're dereferencing the pointer at index x
in the "spine", and then getting the element at index "y" in the "rib". Here's a nice diagram illustrating this structure:
You can read comp.lang.c FAQ list · Question 6.16: How can I dynamically allocate a multidimensional array? (also the source of the image above) for more information.
Another option is to actually allocate a 2D array for your matrix (my preferred method). This requires a compiler with support for some C99 constructs, but all the major compilers except the Microsoft C compiler (e.g. gcc and clang) seem to support this by default. Here's an example:
int (*matrix)[colCount] = (int(*)[colCount]) malloc(sizeof(int)*rowCount*colCount);
The weird syntax above is how you declare a pointer to an array in C. The parenthesis around *matrix
are needed to disambiguate it from declaring from an array of pointers. You don't need to cast the result of malloc in C, so equivalently:
int (*matrix)[colCount] = malloc(sizeof(int)*rowCount*colCount);
This allocates a single block of memory for the matrix, and since the compiler knows the length of each row (i.e. colCount
), it can insert the math to calculate the proper address for any 2D reference. For example, matrix[x][y]
is equivalent to ((int*)matrix)[x*colCount+y]
.
I prefer allocating a 2D array because you can do all of the allocation in one line, whereas with the ragged array you have to set the pointer to each row individually, which usually requires another couple lines for a loop.
As for your segfault, this line looks suspicious:
int **mat1 = (int**)malloc(n*sizeof(int));
Since mat1
is type int**
, each entry in mat1
should be an int*
. However, your malloc
is using sizeof(int)
to allocate the memory for the entries! Try this instead:
int **mat1 = (int**)malloc(n*sizeof(int*));
Assuming you're on a 64-bit system, sizeof(int)
is probably 4 (bytes), whereas sizeof(int*)
should be 8 (bytes). That means you're currently allocating half as much memory as you need, which means bad thing will happen when you access the entries in the second half of that array. Using the correct size (sizeof(int*)
) should fix this.
(There might be other problems too, but that's the one that stood out at first glance.)
Upvotes: 9