There's two main options:
- Allocate each row separately
- Allocate a single bloc containing all rows
If you want to sometimes extend individual rows then you have to use the first option. The second option forces you to have all rows the same length.
The only problem with the second option is that you cannot then use double-dereference syntax, since there is only a single dereference happening. You'd have to access in a different way, for example:
// global
int *multiArray;
size_t multiArray_num_columns;
#define MARRAY(row, col) my_multiarray[(row) * multiArray_num_columns + (col)]
// in a function
multiArray_num_columns = columns;
multiArray = malloc(rows * columns * sizeof *multiArray);
MARRAY(3, 2) = 20;
There is a third option (which I don't like but some people do):
- Allocate a single bloc, and put a table of pointers at the start of it
This gains you the double-dereference syntax but has no other benefits; its downside is that it's a lot more coding, and it may incur a runtime penalty (two dereferences can cost more than one dereference).
Update: here is the code for allocating each row separately (this gets asked a lot but I couldn't find a good duplicate!)
// global
int **multiArray;
// in function
multiArray = malloc( rows * sizeof *multiArray );
for (size_t row = 0; row < rows; ++row)
multiArray[row] = malloc( columns * sizeof **multiArray );
You should check all of these results against NULL
and exit if they failed.
Using the pattern ptr = malloc( NUM * sizeof *ptr );
guarantees to allocate the right amount of memory even if you later change the type of ptr
.