Following are different ways to create a 2D array on the heap (or dynamically allocate a 2D array).
In the following examples, we have considered ‘r‘ as number of rows, ‘c‘ as number of columns and we created a 2D array with r = 3, c = 4 and the following values
1 2 3 4 5 6 7 8 9 10 11 12
1) Using a single pointer and a 1D array with pointer arithmetic:
A simple way is to allocate a memory block of size r*c and access its elements using simple pointer arithmetic.
#include <stdio.h> #include <stdlib.h> int main( void )
{ int r = 3, c = 4;
int * ptr = malloc ((r * c) * sizeof ( int ));
/* Putting 1 to 12 in the 1D array in a sequence */
for ( int i = 0; i < r * c; i++)
ptr[i] = i + 1;
/* Accessing the array values as if it was a 2D array */
for ( int i = 0; i < r; i++) {
for ( int j = 0; j < c; j++)
printf ( "%d " , ptr[i * c + j]);
printf ( "\n" );
}
free (ptr);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity : O(R*C), where R and C is size of row and column respectively.
Auxiliary Space: O(R*C), where R and C is size of row and column respectively.
2) Using an array of pointers
We can create an array of pointers of size r. Note that from C99, C language allows variable sized arrays. After creating an array of pointers, we can dynamically allocate memory for every row.
#include <stdio.h> #include <stdlib.h> int main()
{ int r = 3, c = 4, i, j, count;
int * arr[r];
for (i = 0; i < r; i++)
arr[i] = ( int *) malloc (c * sizeof ( int ));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf ( "%d " , arr[i][j]);
/* Code for further processing and free the
dynamically allocated memory */
for ( int i = 0; i < r; i++)
free (arr[i]);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity: O(R*C)
Here R and C is size of row and column respectively.
Auxiliary Space: O(R*C)
The extra space is used to store the elements of the matrix.
3) Using pointer to a pointer
We can create an array of pointers also dynamically using a double pointer. Once we have an array pointers allocated dynamically, we can dynamically allocate memory and for every row like method 2.
#include <stdio.h> #include <stdlib.h> int main()
{ int r = 3, c = 4, i, j, count;
int ** arr = ( int **) malloc (r * sizeof ( int *));
for (i = 0; i < r; i++)
arr[i] = ( int *) malloc (c * sizeof ( int ));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf ( "%d " , arr[i][j]);
/* Code for further processing and free the
dynamically allocated memory */
for ( int i = 0; i < r; i++)
free (arr[i]);
free (arr);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity: O(R*C)
Here R and C is size of row and column respectively.
Auxiliary Space: O(R*C)
The extra space is used to store the elements of the matrix.
4) Using double pointer and one malloc call
#include<stdio.h> #include<stdlib.h> int main()
{ int r=3, c=4, len=0;
int *ptr, **arr;
int count = 0,i,j;
len = sizeof ( int *) * r + sizeof ( int ) * c * r;
arr = ( int **) malloc (len);
// ptr is now pointing to the first element in of 2D array
ptr = ( int *)(arr + r);
// for loop to point rows pointer to appropriate location in 2D array
for (i = 0; i < r; i++)
arr[i] = (ptr + c * i);
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf ( "%d " , arr[i][j]);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity: O(R*C)
Here R and C is size of row and column respectively.
Auxiliary Space: O(R*C)
The extra space is used to store the elements of the matrix.
Thanks to Trishansh Bhardwaj for suggesting this 4th method.
5) Using a pointer to Variable Length Array.
The dimensions of VLA are bound to the type of the variable. Therefore one form a pointer to an array with run-time defined shape.
The pointer has to be dereferenced before subscripting with syntax (*arr)[i][j].
#include <stdio.h> #include <stdlib.h> int main()
{ int row = 3, col = 4, i, j, count;
int (*arr)[row][col] = malloc ( sizeof *arr);
count = 0;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
(*arr)[i][j] = ++count;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf ( "%d " , (*arr)[i][j]);
free (arr);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity: O(R*C)
Here R and C is size of row and column respectively.
Auxiliary Space: O(R*C)
The extra space is used to store the elements of the matrix.
6) Using a pointer to the first row of VLA
Similar to 5 but allows arr[i][j] syntax.
#include <stdio.h> #include <stdlib.h> int main()
{ int row = 3, col = 4, i, j, count;
int (*arr)[col] = calloc (row, sizeof *arr);
count = 0;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
arr[i][j] = ++count;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf ( "%d " , arr[i][j]);
free (arr);
return 0;
} |
1 2 3 4 5 6 7 8 9 10 11 12
Time Complexity: O(R*C)
Here R and C is size of row and column respectively.
Auxiliary Space: O(R*C)
The extra space is used to store the elements of the matrix.