10

Conosco algoritmi per allocare/deallocare un array 2D in modo dinamico, tuttavia non sono molto sicuro dello stesso per gli array 3D.
Usando questa conoscenza e un po 'di simmetria, ho trovato il seguente codice.
(Ho avuto difficoltà a visualizzare in 3D durante la codifica).allocazione dinamica/deallocazione di array 2D e 3D

Si prega di commentare la correttezza e suggerire qualsiasi alternativa migliore (in termini di efficienza o intuitivamente), se presente.
Inoltre, penso che entrambi questi array 2D e 3D siano accessibili normalmente come array statici come arr2D [2] [3] e
arr3D [2] [3] [2]. Destra?

Codice in 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); 
} 

Codice in 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); 
} 

risposta

11

È inoltre possibile allocare un array e calcolare indici individuali. Ciò richiede un minor numero di chiamate allocator e risultati in termini di minore frammentazione e migliore utilizzo della cache.

typedef struct { 
    int a; 
    int b; 
    int* data; 
} Int2d; 

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

Ora arr2d[r][c] diventa arr2d.data[r * arr2d.b + c]. La deallocazione è un singolo gratuito() di distanza. Come bonus sei sicuro di mantenere sempre le tue dimensioni di array dinamici con te.

Estrapolando a 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]; 

Si dovrebbe incapsulare queste operazioni indici (e le (de-) allocazioni per questo) in una funzione o macro separata.

(I nomi per r, c, e d potrebbero essere migliori — Stavo andando per riga, colonna e profondità. Mentre a, b, e c sono i limiti delle loro dimensioni corrispondenti, potresti preferire qualcosa come n1 , n2, n3 lì, o anche utilizzare un array per loro.)

+0

è anche possibile allocare una matrice n dimensionale in un singolo blocco abbastanza grande da contenere sia i puntatori che i dati. In questo modo puoi andare int ***** array = allocate (sizeof (int), 10, 10, 10, 10, 10, 0); allocare un array int 5D e indicizzarlo con array [a] [b] [c] [d] [e] senza la necessità di calcolare gli indici. L'ho usato quando avevo bisogno di sostituire gli array di stack di grandi dimensioni con quelli di heap per codificare per lavorare su telefoni con dimensioni di stack limitate senza la necessità di eseguire gravi correzioni al codice che indicizza gli array. Vedi qui: https://sourceforge.net/p/gnugos60/code/HEAD/tree/trunk/GNUGoS60/common/src/ndMalloc.cpp – idij

4

arr3d dovrebbe essere un puntatore tripla e non solo un int. Sembra Altrimenti 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 è un puntatore a puntatore a puntatore, in modo arr3D [i] è un puntatore a puntatore e arr3D [i] [j] solo un puntatore. È corretto rilasciare prima la dimensione più bassa in un ciclo, quindi risalire le dimensioni finché non viene rilasciato arr3D stesso.

Inoltre è più idiomatico dare a malloc la dimensione del tipo puntato implicitamente. Invece di:

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

Make it:

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

E sì, tali allocati dinamicamente array multidimensionali sono accessibili proprio come allocato in modo statico array multidimensionali.

+0

+1 per buoni consigli. – Ankur

1

Si può vedere il codice qui sotto:

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

Per maggiori dettagli si veda questo link 3d array

0

Questa è una versione dell'idea nella questione, ma utilizzando un solo malloc, ispirato l'altra risposte. Consente un uso intuitivo delle staffe quadre e una facile pulizia. Spero che non faccia alcuna ipotesi specifica per l'implementazione del compilatore.

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