The formal argument arr
in the function is a separate object from the actual argument p
in main
- any changes to arr
are not applied to p
, so p
is never set to point to the memory you just allocated.
What you will have to do is pass a pointer to p
:
void doArr(int x, int y, int ***arr){
*arr=(int **)malloc(sizeof(int *)*x); // note type of sizeof - you're allocating an array of int *, not int
for (int i=0;i<y;i++){
*(*arr+i)=(int *)malloc(sizeof(int)*y);
}
}
...
doArr( 5, 2, &p );
Or, return arr
and assign the result of doArr
to p
:
int **p = doArr( int x, int y )
{
int **arr = malloc(...);
...
return arr;
}
p = doArr( 5, 2 );
As Emanuel P notes, do
is a keyword, so you can't use it as a function name.
A couple of style notes:
Since C89, malloc
returns void *
and does not require an explicit cast, and many of us will recommend against using it. It just adds visual noise and creates an extra maintenance burden.
Similarly, I often recommend that the operand of sizeof
be your target expression, not a type name. Again, this eases your maintenance headaches if you change the type of the destination pointer.
Use array notation instead of pointer arithmetic where possible. It's easier to read and follow, and you're less likely to make a mistake.
Finally, always check the result of a malloc
, calloc
, or realloc
call.
I'd rewrite your doArr
function as follows:
void doArr(int x, int y, int ***arr)
{
*arr = malloc( sizeof **arr * x );
if ( *arr )
{
for ( int i = 0; i < y; i++ )
{
(*arr)[i] = malloc( sizeof *(*arr)[i] * y );
}
}
}
and call it as
doArr( 5, 2, &p );