Comment initialiser un tableau 3D contigu en C

Je sais comment faire un tableau potentiel non contigu de la manière suivante:

int main () { int ***array = (int***)malloc(3*sizeof(int**)); int i, j; for (i = 0; i < 3; i++) { // Assign to array[i], not *array[i] (that would dereference an uninitialized pointer) array[i] = (int**)malloc(3*sizeof(int*)); for (j = 0; j < 3; j++) { array[i][j] = (int*)malloc(3*sizeof(int)); } } array[1][2][1] = 10; return 0; } 

avec le code ci-dessus, le tableau [0] [j] blocs peut être non contigu. Pour devenir contigu, je pense que nous devons malloc de cette façon

 int* array = (int*)malloc(3*3*3*sizeof(int)); int** y = (int**)malloc(3*3*sizeof(int**)); int*** x = (int***)malloc(3*sizeof(int***)); for(i = 0; i < 3; i++) { vals = vals + i*m*n; x[i] = &vals; for(j = 0; j < 3; j++) { x[i][j] = vals + j * n; } } 

Cependant, j’ai eu troulbe avec l’atsortingbution d’adresse. Je ne suis pas programmeur ca, quelqu’un peut-il corriger ma faute? Merci d’avance…

 int*** x = (int***)malloc(3*sizeof(int***)); 

devrait être

 int*** x = (int***)malloc(3*sizeof(int**)); 

L’initialisation peut maintenant être:

  for(i = 0; i < 3; i++) { x[i] = y + 3*i; for(j = 0; j < 3; j++) { x[i][j] = array + i*3*3 + j*3; } } 

Ainsi, x[0] pointe sur le premier élément de y , x[1] sur le quasortingème, etc. Et x[0][0] = y[0] sur le premier du array , x[0][1] = y[1] au quasortingème de la array , etc.

Pour allouer un tableau 3D contigu , il vous suffit de procéder comme suit (en supposant que toutes les dimensions sont connues au moment de la compilation):

 #define D0 ... #define D1 ... #define D2 ... ... T (*arr)[D1][D2] = malloc( sizeof *arr * D0 ); // for any type T ... arr[i][j][k] = some_value(); ... 

arr est déclaré en tant que pointeur sur un tableau D1 x D2 . Nous allouons ensuite assez d’espace pour D0 ces tableaux ( sizeof *arr == sizeof (T [D1][D2]) ).

Avec cette méthode, toute la mémoire de la masortingce est allouée de manière contiguë. En outre, il vous suffit d’un appel free pour free le tout.

Si vos dimensions ne sont pas connues avant l’exécution et que vous utilisez un compilateur C99 ou un compilateur C2011 qui prend en charge les tableaux de longueur variable, vous avez encore de la chance:

 size_t d0, d1, d2; ... T (*arr)[d1][d2] = malloc( sizeof *arr * d0 ); 

La question principale est de savoir comment passer cela comme argument à une fonction. En supposant que D1 et D2 soient connus au moment de la compilation, si vous décidez de le passer comme

 foo( arr, D0 ); 

alors le prototype pour foo devra être

 void foo( T (*aptr)[D1][D2], size_t n ) { ... aptr[i][j][k] = ...; } 

et cela ne sera utile que pour n tableaux de la taille D1 x x D2 .

Si vous choisissez la route VLA, vous devez également déclarer les dimensions et leur transmettre les valeurs suivantes:

 void foo( size_t d0, size_t d1, size_t d2, T (*aptr)[d1][d2] ) // d1 and d2 *must* be // declared before aptr { ... arr[i][j][k] = some_value(); } void bar( void ) { size_t d0, d1, d2; ... T (*arr)[d1][d2] = malloc( sizeof *arr * d0 ); ... foo( d0, d1, d2, arr ); ... } 

Si vous n’avez pas de compilateur prenant en charge les VLA, mais que vous souhaitiez tout de même allouer cette mémoire de manière contiguë, vous devrez alors suivre la route ancienne – allouez-le en tant que tableau 1D et calculez vos décalages manuellement:

 T *arr = malloc( sizeof *arr * d0 * d1 * d2 ); ... arr[i * d0 * d1 + j * d1 + k] = some_value(); 

J’utilise des méthodes très soignées pour allouer des tableaux multidimensionnels avec des pointeurs de ligne. Les fonctions multi_malloc et multi_free peuvent être utilisées pour des tableaux de dimensions et de types arbitraires arbitraires. Elles fonctionnent essentiellement sur toutes les plateformes et à partir de C et C ++.

Vous pouvez allouer, par exemple, un tableau à 3 dimensions avec des pointeurs de lignes de manière récursive. Par exemple, un tableau dimensionnel 10x20x30

 float*** data = (float***) multi_malloc(sizeof(float),3, 10,20,20); 

éléments d’access tels que

 data[2][3][4] = 2.0; 

et libérer tout comme (données ainsi que les pointeurs de ligne)

 multi_free(data,3); 

L’en-tête, qui devrait faire partie de C, à mon avis

 #pragma once #include  #include  #include  #include  #if (defined(_MSC_VER) && defined(_WIN32)) // Note when used inside a namespace, the static is superfluous # define STATIC_INLINE_BEGIN static inline //__forceinline # define STATIC_INLINE_END #elif (defined(__GNUC__)) # define STATIC_INLINE_BEGIN static inline # if defined(__CYGWIN__) # define STATIC_INLINE_END # else # define STATIC_INLINE_END __atsortingbute__ ((always_inline)) # endif #endif STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) STATIC_INLINE_END; STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) STATIC_INLINE_END; /** * Allocate multi-dimensional array and establish row pointers * * @param s size of each element * @param d number of dimension * * @return */ STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) { char* tree; va_list ap; /* varargs list traverser */ size_t max, /* size of array to be declared */ *q; /* pointer to dimension list */ char **r, /* pointer to beginning of the array of the * pointers for a dimension */ **s1, *t; /* base pointer to beginning of first array */ size_t i, j; /* loop counters */ size_t *d1; /* dimension list */ va_start(ap,d); d1 = (size_t *) malloc(d*sizeof(size_t)); for(i=0;i 

Vous pouvez allouer de la mémoire pour la mémoire tampon d’éléments, chaque élément étant un tableau à deux dimensions. Donc, il s’agit bien d’un tableau en trois dimensions:

 #include  #include  #include  #define N 3 int main() { int (*array)[N][N] = malloc(N * N * N * sizeof(int)); /* set 0 to all values */ memset(array, 0, N * N * N * sizeof(int)); /* use as 3D array */ array[0][0][0] = 1; array[1][1][1] = 2; array[2][2][2] = 3; int i; /* print array as contiguous buffer */ for (i = 0; i < N * N * N; ++i) printf("i: %d\n", ((int*) array)[i]); free(array); return 0; } 

Donc, en mémoire, le array est placé comme un int array[N][N][N] régulier int array[N][N][N] .

Bien que je pense qu’un tableau normal, créé sur la stack, serait le mieux:

 int array[3][3][3];//can avoid a lot of free() calls later on 

Voici un moyen de créer dynamicment un tableau 3D:
(J’utilise calloc ici au lieu de malloc car cela crée un espace mémoire initialisé)

 int *** Create3D(int p, int c, int r) { int ***arr; int x,y; arr = calloc(p, sizeof(arr)); //memory for int for(x = 0; x < p; x++) { arr[x] = calloc(c ,sizeof(arr)); //memory for pointers for(y = 0; y < c; y++) { arr[x][y] = calloc(r, sizeof(int)); } } return arr; } 

L'utilisation pourrait être:

 int ***array = Create3D(3,3,3); for(i=0;i<3;i++) for(j=0;j<3;j++) for(k=0;k<3;k++) array[i][j][k] = (i+1)*(j+1)*(k+1); 

Notez que le retour de [c] [m] [re] alloc () n'est pas transt dans cet exemple. Bien que cela ne soit pas ssortingctement interdit en C, cela n'est pas recommandé. (ce n'est pas le cas en C ++, où il est requirejs)
Gardez à l'esprit , tout ce qui est alloué doit être libéré. La libération de l’avis se fait dans l’ordre inverse de l’allocation:

 void free3D(int ***arr, int p, int c) { int i,j; for(i=0;i 

L'utilisation pourrait être:

 free3D(array,3,3);