If you want to allocate the whole structure with one malloc
you could use
typedef struct
{
int rows;
int cols;
double data[1];
} Matrix;
In contrast to the other answers this allows to use a single free
.
If your compiler supports arrays of size 0 you can also use double data[0];
.
From C99 onward you can use an array without dimension in the structure: double data[];
, see https://stackoverflow.com/a/2061038/10622916
Instead of calculating the size for malloc
by adding the size of the structure fields' types you should better use sizeof
or offsetof
with the structure type Matrix
because there may be some padding. (Probably not in your case but this depends on compiler implementation and your structure fields.)
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h> // for offsetof
typedef struct
{
int rows;
int cols;
double data[1];
// or with C99: double data[];
} Matrix;
Matrix *initMatrix(int rows, int cols)
{
Matrix *ptr;
double *data;
ptr = (Matrix *)malloc(
offsetof(Matrix, data) // = size of Matrix without double data[1];
// with C99's "double data[];" or with the non-standard
// "double data[0];" you can replace offsetof(...) with: sizeof(Matrix)
+ sizeof(double) * rows * cols); // dynamic array size
if(ptr == NULL) {
perror("malloc failed");
} else {
// save rows and columns for later accessing the matrix
ptr->rows = rows;
ptr->cols = cols;
data = ptr->data;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
*(data) = 0;
data++;
}
}
}
return ptr;
}
int main(void)
{
Matrix *mptr = initMatrix(2, 2);
// use matrix
// a single free is sufficient with the approach above
free(mptr); mptr = NULL;
return 0;
}
Instead of incrementing the pointer data
you can calculate the array index
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
ptr->data[i * cols + j] = 0;
}
}
Or for the 0-initialization you can use memset
memset(ptr->data, 0, sizeof(double) * rows * cols);
Or use calloc(1, offsetof(Matrix, data) + sizeof(double) * rows * cols);
instead of malloc
to get zero initialized memory.