Reputation: 3
I will go straight to what I'm asking for, I also see some similar question but is not what I'm looking for...so it seems I have to ask with a new forum. I'm preparing myself for a future examination, where is not required the pointer, but I would like to get some extra information and abilities. Here's the code followed by the question... I'm using Fedora 33, I know is different from some IDE on Windows (ex: Visual Studio or Dev C++)
/* It's just a simple test, if this work I will get myself into a more complicated one, as you could read in the
* forum, I'm getting ready ( just a recheck of my abilities ) for an universitary examinaton. */
#include <stdio.h>
#include <stdlib.h>
#define N 5
void casual_generation(int** mat);
void prompt_print(int** mat);
int main()
{
int **mat[N][N];
casual_generation(**mat);
prompt_print(**mat);
}
void casual_generation(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
Somebody else on the forum used malloc, struct or other stuff, as you can see in this picture, when I try to execute him it says "Segmentation fault (core dumped)" screen error Where is my error? And if you want, can you also send me the version with the passed value pointer? Thanks for whoever will give me an answer, and time dedicated.
Upvotes: 0
Views: 1563
Reputation: 14117
As you can find a detailed explanation why the code crashed in the other answer I will only propose a quite elegant solution that uses a neat though little known feature from C99 called Variable Length Arrays (aka VLA).
#include <stdio.h>
#include <stdlib.h>
void casual_generation(int n, int mat[n][n]);
void prompt_print(int n, int mat[n][n]);
int main()
{
const int N = 5;
int mat[N][N];
casual_generation(N, mat);
prompt_print(N, mat);
}
void casual_generation(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
It compiles in pedantic mode with no warnings and it works like a charm. VLA were introduced to C to simplify numerical computation over multidimensional arrays.
Upvotes: 0
Reputation: 310980
This declaration
int **mat[N][N];
does not make a sense. It means that you have a matrix elements of which are pointers of the type int **
. But you need a matrix elements of which are integer numbers of the type int
. That is you need a declaration like this
int mat[N][N];
So now you have a two-dimensional array (or matrix) of integers.
As you are going to pass this two-dimensional array to functions then used as an argument expression it is converted to pointer to its first element of the type int ( * )[N]
.
Correspondingly the functions that accepts such an array should be declared like
void casual_generation( int mat[][N], size_t n );
void prompt_print( int mat[][N], size_t n );
or (that is fully equivalent) like
void casual_generation( int ( * mat )[N], size_t n );
void prompt_print( int ( *mat )[N], size_t n );
because the compiler adjusts function parameters having array types to pointers to array element types.
Now for example the first function can be defined the following way
void casual_generation( int ( * mat )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
mat[i][j] = rand() % 50;
}
}
}
And the function can be called like
casual_generation( mat, N );
A similar way can be defined the function prompt_print
.
Using the second parameter makes the function more general. For example it can be called for two-dimensional arrays with different numbers of rows.
Now I will explain why you are getting a segmentation fault in your original code.
You have this declaration
int **mat[N][N];
a two dimensional array of pointers of the type int **
.
Then you are using the expression **mat
as an argument of function calls like this
casual_generation(**mat);
Then you are applying the dereference operator like *mat
the array designator is converted to pointer to its first element (row) having the type int ** ( * )[N]
. So dereferencing this pointer you get the first row of your array int **[N]
. Applying the second time the dereferenced operator to this expression that has an array type the used expression is again is converted to pointer to its first element of the type int **( * )
. That is it points to the first element of the first row of the original two-dimensional array. Dereferencing this pointer you get the first element of the type int **
. This uninitialized pointer with indeterminate value the function accepts as its argument.
Thus dereferencing this first uninitialized element of the original matrix within the function
mat[i][j] = rand() % 50;
^^^
you get a segmentation fault. The reason of the fault is the incorrect matrix and the corresponding function parameter as it was shown above in tbe beginning of the answer.
Upvotes: 2
Reputation: 1573
You meant to do
Int mat[N][N];
and
casual_generation(mat);
prompt_print(mat);
By passing **mat
you are passing mat[0][0]
that is an int
, but you want to pass the whole matrix which is a pointer to pointers to int (i.e. int **
)
And you may want to introduce srand()
in your code.
Just to make things clear:
mat
is of type int **
and it's the whole matrix (or if you want it's a pointer to the first row)
*mat
is of type int *
and it's the first row of the matrix (or if you want it's a pointer to the first element of the first row)
**mat
is of type int
and it's the first element of the first row of the matrix
Upvotes: 0
Reputation: 1510
int **mat[N][N];
Here, you defined a double pointer to a 2D array. You only need to use one of those - a double pointer or a 2D array, like so:
int mat[N][N];
However, the bigger problem comes from trying to interchange 2D arrays and double pointers. This isn't possible in C since the 2D array is laid out flat in memory.
You need to create an array mat_ptr
of pointers yourself and then pass that to casual_generation
and prompt_print
.
Finally, these casual_generation
and prompt_print
functions expect to be given a pointer, so you shouldn't dereference the pointer with **
before calling the function.
The final working code is:
int main()
{
int mat[N][N];
int *mat_ptr[N];
for (int i = 0; i < N; i++)
mat_ptr[i] = mat[i];
casual_generation(mat_ptr);
prompt_print(mat_ptr);
}
Upvotes: 0
Reputation: 1350
Where is my error?
The "Segmentation fault" error happens because you define the variable mat
as a pointer, but don't allocate any memory for it to point to.
int **mat[N][N];
Upvotes: 1