how does malloc know that first it has to allocate a array of pointers, each of which pointer points to a one-dimensional array?
It doesn't; malloc
simply allocates the number of bytes you specify, it has no working knowledge of how those bytes are structured into an aggregate data type.
If you're trying to dynamically allocate a multidimensional array, you have several choices.
If you're using a C99 or C2011 compiler that supports variable length arrays, you could simply declare the array as
int rows;
int cols;
...
rows = ...;
cols = ...;
...
int array[rows][cols];
There are a number of issues with VLAs, though; they don't work for very large arrays, they can't be declared at file scope, etc.
A secondary approach is to do something like the following:
int rows;
int cols;
...
rows = ...;
cols = ...;
...
int (*arrayPtr)[cols] = malloc(sizeof *arrayPtr * rows);
In this case, arrayPtr
is declared as a pointer to an array of int
with cols
elements, so we're allocating rows
arrays of cols
elements each. Note that you can access each element simply by writing arrayPtr[i][j]
; the rules of pointer arithmetic work the same way as for a regular 2D array.
If you aren't working with a C compiler that supports VLAs, you'll have to take a different approach.
You can allocate everything as a single chunk, but you'll have to access it as a 1-d array, computing the offsets like so:
int *arrayPtr = malloc(sizeof *arrayPtr * rows * cols);
...
arrayPtr[i * rows + j] = ...;
Or you can allocate it in two steps:
int **arrayPtr = malloc(sizeof *arrayPtr * rows);
if (arrayPtr)
{
int i;
for (i = 0; i < rows; i++)
{
arrayPtr[i] = malloc(sizeof *arrayPtr[i] * cols);
if (arrayPtr[i])
{
int j;
for (j = 0; j < cols; j++)
{
arrayPtr[i][j] = some_initial_value();
}
}
}
}