The program you want should look like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct matriz mat;
struct matriz {
int lin;
int col;
int *arr;
};
mat* cria(int lin, int col) {
mat *m = malloc(sizeof(mat));
m->lin = lin;
m->col = col;
m->arr = malloc(lin * col * sizeof(int));
return m;
}
void destroi(mat *m) {
if (m == NULL) return;
free(m->arr);
free(m);
}
int ler_elemento(mat *m, int i, int j) {
return m[i * m->col + j];
}
int definir_elemento(mat *m, int i, int j, int valor) {
m[i * m->col + j] = valor;
}
void exibe(mat *m) {
for (int i = 0; i < m->lin; i++) {
for (int j = 0; j < m->col; j++) {
printf("%3d ", ler_elemento(m, i, j));
}
printf("\n");
}
}
int main() {
mat *m;
m = cria(2, 2);
definir_elemento(m, 0, 0, 24);
definir_elemento(m, 0, 1, 16);
definir_elemento(m, 1, 0, 13);
definir_elemento(m, 1, 1, 56);
exibe(m);
destroi(m);
return 0;
}
Note that I created the ler_elemento
and definir_elemento
functions to center, abstract, and encapsulate the logic of accessing the elements in the correct positions. In this way, the other parts of the code do not have to worry about the more complicated details of how to find the correct position in the matrix element array, and you will not even have to worry about knowing that the mat
structure has an array there inside. So if you later want to change how the mat
structure organizes your data, only the ler_elemento
, definir_elemento
, and cria
functions will need to be changed, which avoids cascade changes, where the change of a small detail would force the need to promote major changes in the whole code.
I also added a function to deallocate mat
. It is a good practice to always deallocate what you allocate, and so whenever you have a function that creates something by means of dynamic memory allocation, you should immediately have to hand the function that deallocates the same thing. >
As for sizeof(m->arr)
, this will give you the size of the m->arr
pointer rather than the size of the array. Note that arr
is of type int *
, and therefore sizeof(m->arr)
is the same as sizeof(int *)
. The result is 4 because a pointer to integer occupies 4 bytes on your computer, no matter where that pointer points to, or whether it points to a valid memory address or not.
The purpose of sizeof
is to measure how much static memory a given structure occupies, and it is determined at compile time rather than execution time. For dynamic memory allocation, the size of the data allocated depends on information that is only available at runtime, and therefore there is no way for the compiler to know what it would be. The solution is you calculate the size yourself if you need, and in the end, you do not need that to just display the array on the screen.