Pointeurs avec tableau à deux dimensions

S’il vous plaît examiner le morceau de code suivant

#include  #define ROW_SIZE 2 #define COL_SIZE 2 int main() { int a[ROW_SIZE][COL_SIZE]={{1,2},{3,4}}; // Base address:Pointer to the first element a 1D array printf("Base address of array:%p\n",a); //The value at the base address: should be the address of 1st 1D array printf("Value at the Base address:%p\n",*a); return 0; } 

Sortie obtenue:

 Sample Output: Base address of array:0xbff77434 Value at the Base address:0xbff77434 

D’une manière ou d’une autre, je ne parviens pas à comprendre le concept d’adresse de base d’un tableau 2D et de la valeur de l’adresse de base, qui est la même adresse pour un tableau 1D. S’il vous plaît, expliquez.

Les tableaux ne sont pas des pointeurs et, en C, un tableau multidimensionnel est simplement un tableau de tableaux. Dans de nombreux contextes, l’utilisation du nom d’un tableau “se décompose” en un pointeur sur le premier élément de ce tableau. C’est ce qui se passe dans vos deux déclarations imprimées. Dans le premier cas:

 printf("Base address of array:%p\n",a); 

a devient un pointeur sur le premier élément du tableau, c’est-à-dire un pointeur sur la première ligne de votre tableau. Dans votre cas, cela signifie que vous obtenez un pointeur de type int (*)[2] .

Dans le second cas:

 printf("Value at the Base address:%p\n",*a); 

La même décroissance se produit, mais alors vous déréférenciez ce pointeur. Cela signifie que vous avez déréférencé ce pointeur int (*)[2] vers la première ligne, vous laissant ainsi à nouveau avec un tableau (la première ligne). Ce tableau se décompose en un pointeur sur son premier élément, ce qui vous donne un pointeur int * résultant (sur le premier élément de la première ligne).

Dans les deux cas, l’adresse est la même, car c’est ainsi que le tableau est mis en mémoire. Si nous disions que votre tableau 2D commençait à l’adresse 0 , il ressemblerait à ceci (en supposant un type int 4 octets):

  Address Value 0 1 4 2 8 3 12 4 

L’adresse de la première ligne et l’adresse du premier élément de la première ligne sont toutes deux 0 à 0 .

En restructurant le diagramme dans la question et en consolidant les informations des réponses précédentes, je crée la réponse suivante.

Tableaux et pointeurs

Tableau unidimensionnel

  • Considérons un tableau a de 4 entiers comme a[4]
  • La règle de base est à la fois a et &a pointera vers le même emplacement. Mais ils ne pointent pas vers le même type.
  • &a pointera vers le tableau entier qui est un entier int[] . Le type de pointeur est int(*)[]
  • a , lorsqu’il se désintègre en un pointeur, pointe vers le premier élément du tableau qui est un int . Le type de pointeur est int *

Tableau à deux dimensions

  • Considérons un tableau contenant deux tableaux 1D, chacun d’eux ayant deux éléments; a[2][2] .
  • Étant donné que le nombre de dimensions augmente, nous avons un niveau de hiérarchie supplémentaire, à savoir &a , a et *a désignent le même emplacement, mais ils ne désignent pas le même type.
  • &a pointera vers le tableau entier qui est int[][] . Le type de pointeur est int(*)[][] .
  • a , lorsqu’il se désintègre en un pointeur, pointe vers le premier élément du tableau 2D qui est un int[] . Le type de pointeur est int(*)[]
  • En utilisant *a , nous dé-référencons le pointeur sur un tableau 1D. Par conséquent, nous aurons un int * pointant vers la première valeur entière du tableau 2D.

Je pense que le formatage de votre sortie vous jette. Vous avez raison, l’adresse du premier élément du tableau (0xbff77434) est différente de la valeur (1). Le% p devient confus en essayant de forcer les deux à un format de “pointeur”.

Et oui, Carl a également raison.

Si vous voulez voir ce qu’il y a au premier élément, vous pouvez dire n’importe lequel:

 printf("%i", a[0][0]); int* p = &a[0][0]; // point 'p' to the beginning of 'a' // (or) int* p = a; // saying "&a[0][0]" is the same as saying "a" printf("%i", *p); // here, the dereference is what you want 

En ce qui concerne les tableaux 1D vs 2D, ce n’est qu’une question d’interprétation. Tous les deux

 int x[4]; 

et

 int x[2][2]; 

créer des blocs contigus de 4 éléments de taille “int”. Et dans les deux cas, l’expression «x» fait référence à l’adresse de la 0e entrée (l’adresse du tableau, par exemple).

Le tableau bidimensionnel a[2][2] peut être vu comme un tableau monodimensionnel à 4 éléments. Pensez à ce qui se passe lorsque vous convertissez a pointeur en int* :

 int a[2][2] = {{ 1, 2 }, { 3, 4 }}; int* p = (int*) a; // == { 1, 2, 3, 4 } assert(a[1][0] == p[2] == 3); // true int* a0 = a[0]; // the first row in the bidimensional array int* p0 = &p[0]; // the first element in the monodimensional array assert(*a0 == *p0 == 1); // true // Or the long version: assert(a[0][0] == *a0 == a0[0] == p[0] == *p0 == p0[0] == 1); // true // And for the second array in a: int* a1 = a[1]; // the second row in the bidimensional array int p2 = &p[2]; // the third element in the monodimensional array assert(a[1][0] == *a1 == a1[0] == p[2] == *p2 == p2[0] == 3); // true 

Les tableaux a et a[0] pointent fondamentalement vers la même adresse, mais leurs types fournissent des informations sur la manière dont ils peuvent être manipulés.