Allocate memory 2d array in function C

serhii picture serhii · Feb 25, 2013 · Viewed 55.9k times · Source

How to allocate dynamic memory for 2d array in function ? I tried this way:

int main()
{
  int m=4,n=3;
  int** arr;
  allocate_mem(&arr,n,m);
}


void allocate_mem(int*** arr,int n, int m)
{
  *arr=(int**)malloc(n*sizeof(int*));
  for(int i=0;i<n;i++)
    *arr[i]=(int*)malloc(m*sizeof(int));
} 

But it doesn't work.

Answer

Grijesh Chauhan picture Grijesh Chauhan · Feb 25, 2013

Your code is wrong at *arr[i]=(int*)malloc(m*sizeof(int)); because the precedence of the [] operator is higher than the * deference operator: In the expression *arr[i], first arr[i] is evaluated then * is applied. What you need is the reverse (dereference arr, then apply []).

Use parentheses like this: (*arr)[i] to override operator precedence. Now, your code should look like this:

void allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n*sizeof(int*));
  for(int i=0; i<n; i++)
    (*arr)[i] = (int*)malloc(m*sizeof(int));
} 

To understand further what happens in the above code, read this answer.

It is important that you always deallocate dynamically allocated memory explicitly once you are done working with it. To free the memory allocated by the above function, you should do this:

void deallocate_mem(int*** arr, int n){
    for (int i = 0; i < n; i++)
        free((*arr)[i]);
    free(*arr); 
}

Additionally, a better way to create a 2D array is to allocate contiguous memory with a single malloc() function call as below:

int* allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n * sizeof(int*));
  int *arr_data = malloc( n * m * sizeof(int));
  for(int i=0; i<n; i++)
     (*arr)[i] = arr_data + i * m ;
  return arr_data; //free point
} 

To deallocate this memory:

void deallocate_mem(int*** arr, int* arr_data){
    free(arr_data);
    free(*arr);
}

Notice that in the second technique malloc is called only two times, and so in the deallocation code free is called only two times instead of calling it in a loop. So this technique should be better.