allocation / désallocation dynamic de tableaux 2D et 3D

Je connais les algorithmes pour allouer / désallouer un tableau 2D de manière dynamic, mais je ne suis pas sûr de la même chose pour les tableaux 3D.
En utilisant cette connaissance et un peu de symésortinge, j’ai créé le code suivant.
(J’ai eu du mal à visualiser en 3D lors du codage).

Veuillez commenter sur l’exactitude et suggérer une meilleure solution (sur le plan de l’efficacité ou de manière intuitive), le cas échéant.
De plus, je pense que ces tableaux 2D et 3D sont accessibles normalement comme des tableaux statiques comme arr2D [2] [3] et
arr3D [2] [3] [2]. Droite?

Code pour 2D

//allocate a 2D array int** allocate2D(int rows,int cols) { int **arr2D; int i; arr2D = (int**)malloc(rows*sizeof(int*)); for(i=0;i<rows;i++) { arr2D[i] = (int*)malloc(cols*sizeof(int)); } } //deallocate a 2D array void deallocate2D(int** arr2D,int rows) { int i; for(i=0;i<rows;i++) { free(arr2D[i]); } free(arr2D); } 

Code pour la 3D

 //allocate a 3D array int*** allocate3D(int l,int m,int n) { int ***arr3D; int i,j,k; arr3D = (int***)malloc(l * sizeof(int **)); for(i=0;i<l;i++) { arr3D[i] = (int**)malloc(m * sizeof(int*)); for(j=0;j<m;j++) { arr3D[i][j] = (int*)malloc(n*sizeof(int)); } } return arr3D; } //deallocate a 3D array 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); } 

Vous pouvez également allouer un tableau et calculer des index individuels. Cela nécessite moins d’appels d’allocateur et entraîne à la fois moins de fragmentation et une meilleure utilisation du cache.

 typedef struct { int a; int b; int* data; } Int2d; Int2d arr2d = { 2, 3 }; arr2d.data = malloc(arr2d.a * arr2d.b * sizeof *arr2d.data); 

Maintenant arr2d[r][c] devient arr2d.data[r * arr2d.b + c] . Deallocation est un simple libre (). En prime, vous êtes sûr de toujours garder vos tailles de tableaux dynamics avec vous.

Extrapoler en 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]; 

Vous devez encapsuler ces opérations sur les index (et les (dé) allocations) dans une fonction ou une macro séparée.

(Les noms de r, c et d pourraient être meilleurs. J’allais pour ligne, colonne et profondeur. Bien que a, b et c soient les limites de leurs dimensions correspondantes, vous pourriez préférer quelque chose comme n1, n2, n3 là-bas, ou même utiliser un tableau pour eux.)

arr3d devrait être un sortingple pointeur et pas seulement un int. Sinon, ça va:

 void deallocate3D(int*** arr3D,int l,int m) { int i,j; for(i=0;i 

arr3D est un pointeur à pointeur, donc arr3D [i] est un pointeur à pointeur et arr3D [i] [j] juste un pointeur. Il est correct de libérer d'abord la dimension la plus basse dans une boucle, puis de gravir les dimensions jusqu'à ce que arr3D soit lui-même relâché.

De plus, il est plus idiomatique de donner à malloc la taille du type pointé implicitement. Au lieu de:

  arr3D[i] = (int**)malloc(m * sizeof(int*)); 

Fais-le:

  arr3D[i] = (int**)malloc(m * sizeof(*arr3D[i])); 

Et oui, de tels tableaux multidimensionnels alloués dynamicment peuvent être accédés comme des tableaux multidimensionnels alloués de manière statique.

Vous pouvez voir le code ci-dessous:

 #include  #include  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); } 

Pour plus de détails, voir ce lien Tableau 3D

Ceci est une version de l’idée de la question mais en utilisant un seul malloc, inspiré des autres réponses. Il permet une utilisation intuitive des crochets et un nettoyage facile. J’espère qu’il ne fait aucune hypothèse spécifique à l’implémentation du compilateur

 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; }