38 votes

Comment les tableaux 3D sont-ils stockés en C ?

J'ai cru comprendre que les tableaux en C sont alloués par ordre de rangée majeure. Donc, pour un tableau de 2 x 3 :

0  1
2  3
4  5

est stocké en mémoire comme

0 1 2 3 4 5

Cependant, que se passe-t-il si j'ai un tableau 2 x 3 x 2 :

0  1
2  3
4  5

y

6  7
8  9
10 11

Comment sont-elles stockées en mémoire ? C'est juste consécutif comme :

0 1 2 3 4 5 6 7 8 9 10 11

Ou est-ce qu'il y a un autre moyen ? Ou cela dépend-il de quelque chose ?

26voto

aroth Points 28424

À un niveau inférieur, il n'existe pas de tableau multidimensionnel. Il s'agit simplement d'un bloc de mémoire plat, suffisamment grand pour contenir un nombre donné d'éléments. En C, un tableau multidimensionnel est conceptuellement un tableau dont les éléments sont également des tableaux. Donc, si vous le faites :

int array[2][3];

Conceptuellement, vous vous retrouvez avec :

array[0] => [0, 1, 2]
array[1] => [0, 1, 2]

Il en résulte que les éléments sont disposés de manière contiguë dans la mémoire, car array[0] y array[1] ne contiennent pas de données, ce sont juste des références aux deux tableaux internes. Notez que cela signifie que seul le tableau [0, 1, 2] occupent réellement de l'espace dans la mémoire. Si vous étendez ce modèle à la dimension suivante, vous pouvez le constater :

int array[2][3][2];

...vous donnera une structure comme :

array[0] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]
array[1] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]

qui continue d'arranger les éléments consécutivement dans la mémoire (comme ci-dessus, seulement les [0, 1] occupent réellement de l'espace en mémoire, tout le reste n'est qu'une partie d'une référence à l'une de ces entrées). Comme vous pouvez le constater, ce schéma se poursuit quel que soit le nombre de dimensions que vous avez.

Et juste pour le plaisir :

int array[2][3][2][5];

Il vous donne :

array[0] => [0] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [1] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [2] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
array[1] => [0] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [1] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [2] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]

18voto

pmg Points 52636

Toutes les "dimensions" sont stockées consécutivement en mémoire.

Pensez à

    int arr[4][100][20];

vous pouvez dire que arr[1] y arr[2] (de type int[100][20] ) sont contigus
ou que arr[1][42] y arr[1][43] (de type int[20] ) sont contigus
ou que arr[1][42][7] y arr[1][42][8] (de type int ) sont contigus

13voto

sje397 Points 23619

Oui, vous avez raison - ils sont stockés consécutivement. Prenons cet exemple :

#include <stdio.h>

int array3d[2][3][2] = {
  {{0, 1}, {2, 3}, {3, 4}},
  {{5, 6}, {7, 8}, {9, 10}}
};

int main()
{
  int i;
  for(i = 0; i < 12; i++) {
    printf("%d ", *((int*)array3d + i));
  }
  printf("\n");
  return 0;
}

Sortie :

0 1 2 3 3 4 5 6 7 8 9 10

8voto

Thies Heidecke Points 1609

Oui, ils sont juste stockés dans un ordre consécutif. Vous pouvez tester ça comme ça :

#include <stdio.h>

int main (int argc, char const *argv[])
{
  int numbers [2][3][4] = {{{1,2,3,4},{5,6,7,8},{9,10,11,12}}
                          ,{{13,14,15,16},{17,18,19,20},{21,22,23,24}}};

  int i,j,k;

  printf("3D:\n");
  for(i=0;i<2;++i)
    for(j=0;j<3;++j)
      for(k=0;k<4;++k)
        printf("%i ", numbers[i][j][k]);

  printf("\n\n1D:\n");
  for(i=0;i<24;++i)
    printf("%i ", *((int*)numbers+i));

  printf("\n");

  return 0;
}

Cela signifie que les accès à un tableau multi-indexé de dimensions (N,M,L) sont transformés en accès unidimensionnels comme ceci :

array[i][j][k] = array[M*L*i + L*j + k]

6voto

CodeButcher Points 403

Je pense que vous avez répondu à votre propre question. Les tableaux multidimensionnels sont stockés dans l'ordre rangée-major.

Voir la section 3.3.2.1 de la spécification C de l'ANSI (il y a également un exemple spécifique) :

Les opérateurs d'indices successifs désignent un membre d'un ensemble objet de type tableau multidimensionnel. Si E est un tableau à n -dimensions ( n =2) avec les dimensions i x j "x ... x" k , alors E (utilisé autrement que comme une valeur de type lvalue) est converti en un pointeur vers un tableau à ( n -1)-dimensions de dimensions dimensions j "x ... x" k . Si l'opérateur unaire * est appliqué explicitement ou implicitement à ce pointeur de manière explicite, ou de manière implicite à la suite d'une inscription, le résultat est le suivant le résultat est le tableau à ( n -1)-dimensions pointé, qui lui-même est converti en un pointeur s'il est utilisé autrement qu'en tant que lvalue. Il s'ensuit Il s'ensuit que les tableaux sont stockés dans l'ordre majeur des lignes (le dernier indice varie le plus rapidement). varie le plus rapidement).

Pour votre exemple, vous pouvez simplement l'essayer et voir - http://codepad.org/10ylsgPj

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X