web-dev-qa-db-fra.com

Le tableau 2D est-il un double pointeur?

int main()
{
    matrix[2][4] = {{11,22,33,99},{44,55,66,110}};
    int **ptr = (int**)matrix;
    printf("%d%d",**matrix,*ptr);
}

Mais lorsqu'un tableau 2D est transmis en tant que paramètre, il est transtypé en (* matrice) [2] .. quel type le compilateur stocke-t-il sous forme de tableau ... est-il stocké sous forme de tableau 2D ou de double pointeur ou un pointeur vers un tableau .. S'il stocke en tant que tableau, comment interprète-t-il différemment dans différentes situations comme ci-dessus. Veuillez m'aider à comprendre.

37
Angus

Le tableau 2D est-il un double pointeur?

Non. Cette ligne de votre programme est incorrecte:

int **ptr = (int**)matrix;

Cette réponse traite du même sujet

Si vous voulez une image concrète de la façon dont les tableaux multidimensionnels sont implémentés:

Les règles des tableaux multidimensionnels ne sont pas différentes de celles des tableaux ordinaires, il suffit de remplacer le type de tableau "interne" par le type d'élément. Les éléments du tableau sont stockés en mémoire directement les uns après les autres:

matrix: 11 22 33 99 44 55 66 110
        -----------               the first element of matrix
                    ------------  the second element of matrix

Par conséquent, pour adresser l'élément matrix[x][y], Vous prenez the base address of matrix + x*4 + y (4 est la taille du tableau interne).

Lorsque les tableaux sont passés à des fonctions, ils se désintègrent aux pointeurs vers leur premier élément. Comme vous l'avez remarqué, ce serait int (*)[4]. Le 4 Dans le type indiquerait alors au compilateur la taille du type interne, c'est pourquoi cela fonctionne. Lorsque vous effectuez l'arithmétique du pointeur sur un pointeur similaire, le compilateur ajoute des multiples de la taille de l'élément, donc pour matrix_ptr[x][y], Vous obtenez matrix_ptr + x*4 + y, Qui est exactement le même que ci-dessus.

Le cast ptr=(int**)matrix est donc incorrect. Pour une fois, *ptr Signifierait une valeur de pointeur stockée à l'adresse de la matrice, mais il n'y en a pas. Deuxièmement, il n'y a pas de pointeur vers matrix[1] N'importe où dans la mémoire du programme.

Remarque: les calculs dans ce post supposent sizeof(int)==1, pour éviter une complexité inutile.

40
jpalecek

Non. Un tableau multidimensionnel est un seul bloc de mémoire. La taille du bloc est le produit des dimensions multiplié par la taille du type des éléments, et l'indexation dans chaque paire de supports se décale dans le tableau par le produit des dimensions pour les dimensions restantes. Donc..

int arr[5][3][2];

est un tableau qui contient 30 ints. arr[0][0][0] Donne le premier, arr[1][0][0] Donne le septième (décalages de 3 * 2). arr[0][1][0] Donne le troisième (décalages de 2).

Les pointeurs vers lesquels le tableau se désintègre dépendent du niveau; arr se désintègre en un pointeur vers un tableau int 3x2, arr[0] se désintègre en un pointeur vers un tableau int à 2 éléments, et arr [0] [0] se désintègre en un pointeur vers int.

Cependant, vous pouvez également avoir un tableau de pointeurs et le traiter comme un tableau multidimensionnel - mais cela nécessite une configuration supplémentaire, car vous devez définir chaque pointeur sur son tableau. En outre, vous perdez les informations sur les tailles des tableaux dans le tableau (sizeof donnerait la taille du pointeur). D'un autre côté, vous gagnez la possibilité d'avoir des sous-tableaux de tailles différentes et de changer où les pointeurs pointent, ce qui est utile s'ils doivent être redimensionnés ou réorganisés. Un tableau de pointeurs comme celui-ci peut être indexé comme un tableau multidimensionnel, même s'il est alloué et organisé différemment et que sizeof ne se comportera pas toujours de la même manière avec lui. Un exemple alloué statiquement de cette configuration serait:

int *arr[3];
int aa[2] = { 10, 11 }, 
    ab[2] = { 12, 13 }, 
    ac[2] = { 14, 15 };
arr[0] = aa;
arr[1] = ab;
arr[2] = ac;

Après ce qui précède, arr[1][0] Est 12. Mais au lieu de donner le int trouvé à 1 * 2 * sizeof(int) octets après l'adresse de début du tableau arr, il donne le int trouvé à 0 * sizeof(int) octets après l'adresse pointée par arr[1]. De plus, sizeof(arr[0]) est équivalent à sizeof(int *) au lieu de sizeof(int) * 2.

10
Dmitri

Si vous pouvez utiliser la pile pour ces données (petit volume), vous définissez généralement la matrice:

int matrix[X][Y]

Lorsque vous souhaitez l'allouer dans le tas (grand volume), vous définissez généralement un:

int** matrix = NULL;

puis allouez les deux dimensions avec malloc/calloc. Vous pouvez traiter le tableau 2d comme int ** mais ce n'est pas une bonne pratique car cela rend le code moins lisible. Autre que cela

**matrix == matrix[0][0] is true
0
long404