I have an exam and the teacher want to do a problem. It sound like this. a)Reading information about an array (the function returns a structure associated with an array) b)Reading the elements of an array (the function receives as parameters two integers and a pointer to FILE and returns a pointer to pointer to integer)
the point a) is Matrix* infoM. the point b) is int** readM And I get an error with the returning type
enter code here
#include <stdio.h>
#include <stdlib.h>
typedef struct Matrix{
int rows;
int cols;
int** data;
}Matrix;
Matrix* infoM( int n_rows, int n_cols)
{Matrix Matrix;
int i;
Matrix.rows = n_rows;
Matrix.cols = n_cols;
Matrix.data = (int**)malloc(sizeof(int*) * n_rows);
if(Matrix.data == 0)
{
fprintf(stderr, "err");
exit(EXIT_FAILURE);
}
for(i=0;i<n_rows;i )
{
*(Matrix.data i) = (int*)malloc(sizeof(int)*n_cols);
if(*(Matrix.data i) == 0)
{
fprintf(stderr,"err");
exit(EXIT_FAILURE);
}
}
struct Matrix *m;
m = &Matrix;
return m;
}
int** readM(int n_rows, int n_cols, FILE *in)
{
Matrix* matrix = infoM(n_rows,n_cols);
int i,j;
for(i=0; i<n_rows; i )
{
for(j=0; j<n_cols; j )
{
fscanf(in, "%d",*(matrix->data i) j);
}
}
return matrix;
}
CodePudding user response:
I would use a flexible array member to remove double-pointer - and additional overhead (it removes one level of indirection). Additionally, it simplifies malloc/free (only one needed).
To access data use an array pointer.
typedef struct Matrix{
size_t rows;
size_t cols;
int data[];
}Matrix;
Matrix *createM(size_t rows, size_t cols)
{
Matrix *m = malloc(sizeof(*m) cols * rows * sizeof(m -> data[0]));
return m;
}
Matrix *initM(Matrix *m)
{
int (*data)[m -> cols] = (int (*)[m -> cols])m -> data;
for(size_t row = 0; row < m -> rows; row )
{
for(size_t col = 0; col < m -> cols; col )
{
data[row][col] = rand();
}
}
return m;
}
Use correct types for sizes.
CodePudding user response:
C has a notion of lifetime for variables. Automatic variables (declared in a block of function) reach their end of life at the end of the block (or function...) where they are declared in. And using an object passed its end of life explicetely invokes Undefined Behaviour (close to hell for C programmers).
For that reason you cannot return the address of a local variable. It is called a dangling pointer (Google that word for additional details...).
But C allows to return a whole structure. So a minimal modification of your code could be:
...
Matrix infoM( int n_rows, int n_cols)
{Matrix Matrix;
int i;
Matrix.rows = n_rows;
...
return Matrix;
}
Matrix readM(int n_rows, int n_cols, FILE* in)
{
Matrix matrix = infoM(n_rows, n_cols);
int i, j;
for (i = 0; i < n_rows; i )
{
for (j = 0; j < n_cols; j )
{
fscanf(in, "%d", matrix.data[i] j); // more C idiomatic...
}
}
return matrix;
}
For the same reason, readM
is not allowed to return a pointer inside a local object, because it would be a dangling pointer, but you can again return the struct itself.