10

Je connais les algorithmes pour allouer/désallouer un tableau 2D dynamiquement, 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étrie, j'ai trouvé le code suivant.
(J'ai eu du mal à visualiser en 3D pendant le codage).allocation dynamique/désallocation des tableaux 2D et 3D

S'il vous plaît commenter l'exactitude et suggérer une meilleure alternative (efficacité-sage ou intuitivement), le cas échéant.
En outre, je pense que ces deux tableaux 2D et 3D sont accessibles normalement comme des tableaux statiques comme arr2D [2] [3] et
arr3D [2] [3] [2]. Droite?

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

Répondre

11

Vous pouvez également affecter un tableau et calculer des indices individuels. Cela nécessite moins d'appels d'allocateurs et entraîne 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 seul gratuit() loin. En prime, vous êtes sûr de toujours garder vos tailles de tableaux dynamiques avec vous.

extrapolant 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 devriez résumer ces opérations d'index (et les (DÉ) allocations pour cette question) dans une fonction séparée ou macro. (Les noms de r, c et d pourraient être meilleurs — J'allais chercher ligne, colonne et profondeur Alors que a, b et c sont les limites de leurs dimensions correspondantes, vous pourriez préférer quelque chose comme n1 , n2, n3 là, ou même utiliser un tableau pour eux.)

+0

vous pouvez également allouer un tableau de dimension n dans un seul bloc assez grand pour contenir à la fois des pointeurs et des données. De cette façon, vous pouvez aller int ***** array = allouer (sizeof (int), 10, 10, 10, 10, 10, 0); pour allouer un tableau int 5D, et l'indexer par tableau [a] [b] [c] [d] [e] sans avoir besoin de calculer les indices. J'ai utilisé ceci quand j'ai eu besoin de remplacer les grands tableaux de pile par ceux de tas pour coder pour travailler sur des téléphones avec une taille de pile limitée sans avoir besoin de faire un ajustement sérieux au code indexant les tableaux. Voir ici: https://sourceforge.net/p/gnugos60/code/HEAD/tree/trunk/GNUGoS60/common/src/ndMalloc.cpp – idij

4

arr3d devrait être un triple pointeur et non pas seulement un int. Sinon semble 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 est un pointeur à pointer à-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 d'augmenter les dimensions jusqu'à ce que arr3D lui-même soit libéré.

Il est également plus idiomatique de donner implicitement le sizeof du type pointé malloc. Au lieu de:

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

Make it:

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

Et oui, ces tableaux multidimensionnels alloués dynamiquement sont accessibles comme alloués statiquement tableaux multidimensionnels.

+0

+1 pour de bonnes astuces. – Ankur

1

Vous pouvez voir le code ci-dessous:

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

Pour plus de détails, voir ce lien 3d array

0

Ceci est une version de l'idée dans la question, mais en utilisant une seule malloc, inspiré par l'autre réponses. Il permet une utilisation intuitive des crochets et un nettoyage facile. J'espère que cela ne fait aucune supposition spécifique d'implémentation de 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; 
} 
Questions connexes