Question

En C, je sais que je peux allouer dynamiquement un tableau à deux dimensions sur le tas en utilisant le code suivant:

int** someNumbers = malloc(arrayRows*sizeof(int*));

for (i = 0; i < arrayRows; i++) {
    someNumbers[i] = malloc(arrayColumns*sizeof(int));
}

Il est clair que cela crée en fait un tableau à une dimension de pointeurs sur un tas de tableaux séparés unidimensionnels d'entiers, et « Le système » peut comprendre ce que je veux dire quand je demande:

someNumbers[4][2];

Mais quand je déclare statiquement un tableau 2D, comme dans la ligne suivante ...:

int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];

... une structure similaire ne se crée sur la pile, ou est-il d'une autre forme complètement? (À savoir est-il un tableau 1D de pointeurs? Sinon, quel est-il, et comment les références à ce se cernées?)

En outre, quand je dis: « Le système, » ce qui est réellement responsable de déterminer cela? Le noyau? Ou est-ce le genre de compilateur C dehors lors de la compilation?

Était-ce utile?

La solution

Un tableau à deux dimensions statique ressemble à un tableau de tableaux - il est juste mis en mémoire sur jointive. Les tableaux ne sont pas la même chose que des pointeurs, mais parce que vous pouvez souvent les utiliser à peu près interchangeables, il peut être déroutante parfois. Le compilateur assure le suivi correctement, cependant, ce qui rend la ligne de tout joliment. Vous ne devez être prudent avec les tableaux 2D statiques comme vous le mentionnez, car si vous essayez de passer une à une fonction qui prend un paramètre int **, les mauvaises choses vont se passer. Voici un exemple rapide:

int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};

Dans la mémoire ressemble à ceci:

0 1 2 3 4 5

exactement la même chose que:

int array2[6] = { 0, 1, 2, 3, 4, 5 };

Mais si vous essayez de passer array1 à cette fonction:

void function1(int **a);

vous obtiendrez un message d'avertissement (et l'application ne pourrez pas accéder correctement le tableau):

warning: passing argument 1 of ‘function1’ from incompatible pointer type

Parce qu'un tableau 2D ne sont pas les mêmes que int **. La décomposition automatique d'un tableau dans un pointeur ne va « un niveau profond » pour ainsi dire. Vous devez déclarer la fonction comme:

void function2(int a[][2]);

ou

void function2(int a[3][2]);

Pour tout faire plaisir.

Ce même concept s'étend à n tableaux de dimension. Profitant de ce genre d'affaires drôle que de façon générale dans votre application, il est plus difficile à comprendre, cependant. Alors, soyez prudent là-bas.

Autres conseils

La réponse est basée sur l'idée que C n'a pas vraiment Vous tableaux 2D - il a des tableaux-de-tableaux. Lorsque vous déclarez ceci:

int someNumbers[4][2];

Vous demandez someNumbers être une matrice de 4 éléments, où chaque élément de ladite matrice est du type int [2] (qui lui-même est un tableau de 2 ints).

L'autre partie du puzzle est que les tableaux sont toujours disposées en mémoire jointive. Si vous demandez:

sometype_t array[4];

alors que regardera toujours comme ça:

| sometype_t | sometype_t | sometype_t | sometype_t |

(4 objets sometype_t disposés côte à côte, sans espace entre les deux). Donc, dans votre someNumbers tableau-de-tableaux, ça va ressembler à ceci:

| int [2]    | int [2]    | int [2]    | int [2]    |

Et chaque élément de int [2] lui-même est un tableau, qui ressemble à ceci:

| int        | int        |

Donc dans l'ensemble, vous obtenez ceci:

| int | int  | int | int  | int | int  | int | int  |
unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};

en mémoire est égal à:

unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};

En réponse à votre aussi. Les deux, bien que le compilateur fait la plupart du levage de charges lourdes

Dans le cas des tableaux alloués statiquement, « Le système » sera le compilateur. Il réservera la mémoire comme il le ferait pour toute variable de la pile.

Dans le cas du tableau malloc'd, « Le système » sera celui qui applique malloc (le plus souvent du noyau). Tout le compilateur allouera est le pointeur de base.

Le compilateur va toujours gérer le type comme ce qu'ils sont déclarés, sauf dans l'exemple Carl a donné où il peut comprendre l'utilisation interchangeable. Voilà pourquoi si vous passez dans un [] [] à une fonction qu'il doit assumer qu'il est affecté d'une manière statique à plat, où ** est supposé être un pointeur vers un pointeur.

Pour accéder à un tableau 2D particulier considérer la carte mémoire pour une déclaration de tableau comme indiqué dans le code ci-dessous:

    0  1
a[0]0  1
a[1]2  3

Pour accéder à chaque élément, son suffisant pour passer juste qui ensemble vous intéresse en tant que paramètres à la fonction. Ensuite, utilisez décalage pour la colonne pour accéder à chaque élément individuellement.

int a[2][2] ={{0,1},{2,3}};

void f1(int *ptr);

void f1(int *ptr)
{
    int a=0;
    int b=0;
    a=ptr[0];
    b=ptr[1];
    printf("%d\n",a);
    printf("%d\n",b);
}

int main()
{
   f1(a[0]);
   f1(a[1]);
    return 0;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top