I know about algorithms to allocate/deallocate a 2D array dynamically, however I\'m not too sure about the same for 3D arrays.
Using this knowledge and a bit of symmetry
This is a version of the idea in the question but using only one malloc, inspired by the other answers. It allows intuitive use of the square brackets and easy cleaning. I hope it does not make any compiler implementation specific assumption.
int main(int argc, char *argv[])
{
int **array, i, j;
array = allocate2d(3, 4);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
array[i][j] = j + i + 1;
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("array[%d][%d] = %d\n", i, j, array[i][j]);
}
}
free(array);
return EXIT_SUCCESS;
}
int **allocate2d(int x, int y)
{
int i;
int **array = malloc(sizeof(int *) * x + sizeof(int) * x * y);
for (i = 0; i < x; i++)
{
array[i] = ((int *)(array + x)) + y * i;
}
return array;
}
You can see the below code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
// Array 3 Dimensions
int x = 4, y = 5, z = 6;
// Array Iterators
int i, j, k;
// Allocate 3D Array
int *allElements = malloc(x * y * z * sizeof(int));
int ***array3D = malloc(x * sizeof(int **));
for(i = 0; i < x; i++)
{
array3D[i] = malloc(y * sizeof(int *));
for(j = 0; j < y; j++)
{
array3D[i][j] = allElements + (i * y * z) + (j * z);
}
}
// Access array elements
for(i = 0; i < x; i++)
{
printf("%d\n", i);
for(j = 0; j < y; j++)
{
printf("\n");
for(k = 0; k < z; k++)
{
array3D[i][j][k] = (i * y * z) + (j * z) + k;
printf("\t%d", array3D[i][j][k]);
}
}
printf("\n\n");
}
// Deallocate 3D array
free(allElements);
for(i = 0; i < x; i++)
{
free(array3D[i]);
}
free (array3D);
}
For more details see this link 3d array
You can also allocate one array and compute individual indices. This requires fewer allocator calls and results in both less fragmentation and better cache use.
typedef struct {
int a;
int b;
int* data;
} Int2d;
Int2d arr2d = { 2, 3 };
arr2d.data = malloc(arr2d.a * arr2d.b * sizeof *arr2d.data);
Now arr2d[r][c]
becomes arr2d.data[r * arr2d.b + c]
. Deallocation is a single free() away. As a bonus you're sure to always keep your dynamic array sizes with you.
Extrapolating to 3d:
typedef struct {
int a;
int b;
int c;
int* data;
} Int3d;
Int3d arr3d = { 2, 3, 4 };
arr3d.data = malloc(arr3d.a * arr3d.b * arr3d.c * sizeof *arr3d.data);
//arr3d[r][c][d]
// becomes:
arr3d.data[r * (arr3d.b * arr3d.c) + c * arr3d.c + d];
You should encapsulate these index operations (and the (de-)allocations for that matter) in a separate function or macro.
(The names for r, c, and d could be better—I was going for row, column, and depth. While a, b, and c are the limits of their corresponding dimensions, you might prefer something like n1, n2, n3 there, or even use an array for them.)
arr3d should be a triple pointer and not just an int. Otherwise looks OK:
void deallocate3D(int*** arr3D,int l,int m)
{
int i,j;
for(i=0;i<l;i++)
{
for(int j=0;j<m;j++)
{
free(arr3D[i][j]);
}
free(arr3D[i]);
}
free(arr3D);
}
arr3D is a pointer-to-pointer-to-pointer, so arr3D[i] is a pointer-to-pointer and arr3D[i][j] just a pointer. It's correct to release the lowest dimension in a loop first, and then climb up the dimensions until arr3D itself is released.
Also it's more idiomatic to give malloc
the sizeof of the pointed type implicitly. Instead of:
arr3D[i] = (int**)malloc(m * sizeof(int*));
Make it:
arr3D[i] = (int**)malloc(m * sizeof(*arr3D[i]));
And yes, such dynamically allocated multi-dimensional arrays can be accessed just as statically allocated multi-dimensional arrays.