int **arr = (int **)malloc(r * sizeof(int *));
how should i interpret the meaning of the above C code ?
int **arr = (int **)malloc(r * sizeof(int *));
how should i interpret the meaning of the above C code ?
The call to malloc()
in:
int **arr = (int **)malloc(r * sizeof(int *));
allocates space for r
pointers to int
, and returns a void *
pointing to the allocation. This pointer is then cast to int **
and assigned to arr
, which is a pointer to a pointer to int
. Thus arr
points to the first element of the allocated region, which is a pointer to int
. Such code may be used in creating a "jagged" array, where each row of the array is allocated separately; this means that the allocations may not be contiguous in memory, so this would not be a true 2d array. See Correctly allocating multi-dimensional arrays to read more about this.
The above is considered bad style, though. Most importantly, using explicit types as arguments of the sizeof
operator should be avoided when possible:
int **arr = (int **)malloc(r * sizeof *arr);
This is less error-prone, and easier to maintain if the type of arr
changes at some point in the life of the code.
Further, there is no need to cast the result of malloc()
in C, so this cast is superfluous and only serves to clutter the code:
int **arr = malloc(r * sizeof *arr);
As a final refinement, I prefer to place the sizeof
expression first in such cases:
int **arr = malloc(sizeof *arr * r);
This is a useless change in the particular case above, but when there is an additional multiplication, e.g.:
int **arr = malloc(sizeof *arr * r * n);
this guarantees that the arithmetic is carried out with a type at least as wide as size_t
, reducing the risk of integer overflow (signed
integer overflow causes undefined behavior in C), and may reduce the risk of unsigned
integer wrap-around (well-defined, but possibly unexpected or unwelcome).
This
int **arr = (int **)malloc(r * sizeof(int *));
is a dynamic allocation of an array of the type int * [r]
that is an array of r
elements that have the type int *
.
To make the declaration more clear consider the following simple program
#include <stdio.h>
int main(void)
{
char * s[] = { "Hello", " ", "user292174" };
const size_t N = sizeof( s ) / sizeof( *s );
char **p = s;
for ( size_t i = 0; i < N; i++ ) printf( "%s", p[i] );
putchar( '\n' );
return 0;
}
Its output is
Hello user292174
Here in the program instead of the type int
there is used type char
for simplicity.
Array designators in expressions with rare exceptions are converted to pointers to their first elements.
So as the type of the array s
is char *
then a pointer to first element of the array s
will have the type char **
.
In the case of the original declaration from the question then there is allocated dynamically an extent of memory that is interpreted as an array of elements of the type int *
. And the starting address of the extent where the first lement of the implyed array will be exist is assigned to the pointer. So the pointer shall have the type int **.
int **arr = (int **)malloc(r * sizeof(int *));
Usually such allocations are used to simulate a two-dimensional array when the number of rows and columns of the array are calculated at run-time.
For example
#include <stdio.h>
#include<stdlib.h>
int main(void)
{
size_t r = 2;
size_t c = 3;
int **arr = (int **)malloc( r * sizeof( int * ) );
for ( size_t i = 0; i < r; i++ )
{
arr[i] = malloc( c * sizeof( int ) );
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
arr[i][j] = c * i + j;
}
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
printf( "%d ", arr[i][j] );
}
putchar( '\n' );
}
for ( size_t i = 0; i < r; i++ )
{
free( arr[i] );
}
free( arr );
return 0;
}
The program output is
0 1 2
3 4 5
If the compiler supports variable length arrays then a two dimensional array can be allocated at once. For example
#include <stdio.h>
#include<stdlib.h>
int main(void)
{
size_t r = 2;
size_t c = 3;
int ( *arr )[c] = (int **)malloc( sizeof( int[r][c] ) );
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
arr[i][j] = c * i + j;
}
}
for ( size_t i = 0; i < r; i++ )
{
for ( size_t j = 0; j < c; j++ )
{
printf( "%d ", arr[i][j] );
}
putchar( '\n' );
}
free( arr );
return 0;
}
The porgram output is the same as shown above.