227 votes

Comment se fait-il que l'adresse d'un tableau soit égale à sa valeur en C?

Dans le bit de code suivant, les valeurs de pointeur et les adresses de pointeur diffèrent comme prévu.

Mais les valeurs et les adresses des tableaux ne le font pas!

Comment se peut-il?

Sortie

 my_array = 0022FF00
&my_array = 0022FF00
pointer_to_array = 0022FF00
&pointer_to_array = 0022FEFC
 
 #include <stdio.h>

int main()
{
  char my_array[100] = "some cool string";
  printf("my_array = %p\n", my_array);
  printf("&my_array = %p\n", &my_array);

  char *pointer_to_array = my_array;
  printf("pointer_to_array = %p\n", pointer_to_array);
  printf("&pointer_to_array = %p\n", &pointer_to_array);

  printf("Press ENTER to continue...\n");
  getchar();
  return 0;
}
 

244voto

Jerry Coffin Points 237758

Le nom d'un tableau évalue généralement à l'adresse du premier élément du tableau, array et &array ont la même valeur (mais de types différents, array+1 et &array+1 va pas être égales si le tableau est plus de 1 élément).

Il y a deux exceptions à cela: lorsque le nom du tableau est un opérande de sizeof ou unaire & (adresse), le nom se réfère au tableau de l'objet lui-même. Ainsi, sizeof array vous donne la taille en octets de l'ensemble de la grappe, pas la taille d'un pointeur.

Pour un tableau défini comme T array[size], il sera de type T *. Quand/si vous l'incrémenter, vous obtenez à l'élément suivant du tableau.

&array évalue à la même adresse, mais compte tenu de la même définition, il crée un pointeur de type T(*)[size] -- c'est à dire, il est un pointeur sur un tableau, et non pas à un seul élément. Si vous incrément de ce pointeur, il va ajouter de la taille de l'ensemble de la grappe, pas la taille d'un seul élément. Par exemple, avec ce code:

char array[16];
printf("%p\t%p", (void*)&array, (void*)(&array+1));

On peut s'attendre à la deuxième pointeur soit 16 de plus que le premier (parce que c'est un tableau de 16 char). Depuis, %p convertit en général pointeurs en hexadécimal, il pourrait ressembler à quelque chose comme:

0x12341000    0x12341010

37voto

Eli Bendersky Points 82298

C'est parce que le nom de la matrice (my_array) est différente à partir d'un pointeur de tableau. C'est un alias de l'adresse d'un tableau, et son adresse est l'adresse de la table elle-même.

Le pointeur est normal C variable sur la pile, cependant. Ainsi, vous pouvez prendre à son adresse, et obtenir une valeur différente de l'adresse, il détient à l'intérieur.

J'ai écrit sur ce sujet ici - s'il vous plaît prendre un coup d'oeil.

29voto

Charles Bailey Points 244082

En C, lorsque vous avez utilisé le nom d'une matrice dans une expression (y compris le passage à une fonction), sauf s'il est l'opérande de l'adresse de (&) de l'opérateur ou de l' sizeof de l'opérateur, il se désintègre à un pointeur vers son premier élément.

C'est, dans la plupart des contextes array est équivalent à &array[0] à la fois le type et la valeur.

Dans votre exemple, my_array type char[100] qui se décompose à une char* lorsque vous passez à printf.

&my_array type char (*)[100] (pointeur de tableau de 100 char). Comme c'est l'opérande de &, c'est l'un des cas my_array n'est pas immédiatement se désintègrent en un pointeur sur son premier élément.

Le pointeur vers le tableau a la même valeur de l'adresse comme un pointeur vers le premier élément du tableau comme un objet array est juste une séquence contiguë de ses éléments, mais un pointeur vers un tableau est un type différent d'un pointeur sur un élément de ce tableau. Ceci est important lorsque vous ne l'arithmétique des pointeurs sur les deux types de pointeur.

pointer_to_array type char * - initialisé à point au premier élément du tableau qu' my_array se désintègre dans l'initialiseur de l'expression et de l' &pointer_to_array type char ** (pointeur vers un pointeur vers un char).

De ces: my_array (après décroissance char*), &my_array et pointer_to_array tous les points directement sur le tableau ou le premier élément du tableau et ont donc la même valeur de l'adresse.

4voto

1voto

Ravi Bisla Points 112

En fait, &myarray et myarray sont l'adresse de base.

Si vous voulez voir la différence au lieu d'utiliser

 printf("my_array = %p\n", my_array);
printf("my_array = %p\n", &my_array);
 

utilisation

 printf("my_array = %s\n", my_array);
printf("my_array = %p\n", my_array);
 

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