Les autres réponses sont correctes, mais aucune d'entre elles ne souligne l'idée qu'il est possible que les trois contiennent la même valeur et qu'elles sont donc incomplètes.
La raison pour laquelle cela ne peut pas être compris à partir des autres réponses est que toutes les illustrations, bien qu'utiles et certainement raisonnables dans la plupart des circonstances, ne couvrent pas la situation où le pointeur x
pointe vers lui-même.
C'est assez facile à construire, mais clairement un peu plus difficile à comprendre. Dans le programme ci-dessous, nous verrons comment nous pouvons forcer les trois valeurs à être identiques.
REMARQUE: le comportement de ce programme n'est pas défini, mais je le publie ici uniquement comme une démonstration intéressante de quelque chose que les pointeurs peuvent faire, mais ne devraient pas .
#include <stdio.h>
int main () {
int *(*x)[5];
x = (int *(*)[5]) &x;
printf("%p\n", x[0]);
printf("%p\n", x[0][0]);
printf("%p\n", x[0][0][0]);
}
Cela se compile sans avertissements en C89 et C99, et la sortie est la suivante:
$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c
Fait intéressant, les trois valeurs sont identiques. Mais cela ne devrait pas être une surprise! Tout d'abord, décomposons le programme.
Nous déclarons x
comme un pointeur vers un tableau de 5 éléments où chaque élément est de type pointeur vers int. Cette déclaration alloue 4 octets sur la pile d'exécution (ou plus selon votre implémentation; sur ma machine, les pointeurs sont de 4 octets), donc x
fait référence à un emplacement mémoire réel. Dans la famille de langages C, le contenu de x
n'est que des ordures, quelque chose qui reste d'une utilisation précédente de l'emplacement, donc x
lui-même ne pointe nulle part - certainement pas vers l'espace alloué.
Donc, naturellement, nous pouvons prendre l'adresse de la variable x
et la mettre quelque part, c'est donc exactement ce que nous faisons. Mais nous allons continuer et le mettre dans x lui-même. Puisque &x
a un type différent de celui x
, nous devons faire un casting pour ne pas recevoir d'avertissements.
Le modèle de mémoire ressemblerait à ceci:
0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+
Ainsi, le bloc de mémoire de 4 octets à l'adresse 0xbfd9198c
contient le modèle de bits correspondant à la valeur hexadécimale 0xbfd9198c
. Assez simple.
Ensuite, nous imprimons les trois valeurs. Les autres réponses expliquent à quoi chaque expression fait référence, donc la relation devrait être claire maintenant.
Nous pouvons voir que les valeurs sont les mêmes, mais seulement dans un sens de très bas niveau ... leurs modèles de bits sont identiques, mais le type de données associé à chaque expression signifie que leurs valeurs interprétées sont différentes. Par exemple, si nous avons imprimé en x[0][0][0]
utilisant la chaîne de format%d
, nous obtiendrions un nombre négatif énorme, donc les «valeurs» sont, en pratique, différentes, mais le modèle de bits est le même.
C'est en fait très simple ... dans les diagrammes, les flèches pointent simplement vers la même adresse mémoire plutôt que vers des adresses différentes. Cependant, alors que nous avons pu forcer un résultat attendu hors d'un comportement non défini, c'est juste cela - non défini. Ce n'est pas du code de production, mais simplement une démonstration par souci d'exhaustivité.
Dans une situation raisonnable, vous utiliserez malloc
pour créer le tableau de 5 pointeurs int et à nouveau pour créer les entiers pointés dans ce tableau.malloc
renvoie toujours une adresse unique (sauf si vous n'avez plus de mémoire, auquel cas elle renvoie NULL ou 0), vous n'aurez donc jamais à vous soucier des pointeurs auto-référentiels comme celui-ci.
J'espère que c'est la réponse complète que vous recherchez. Vous ne devriez pas vous attendre x[0]
, x[0][0]
et x[0][0][0]
être égal, mais ils pourraient l'être si vous y êtes forcé. Si quelque chose vous a dépassé, faites-le moi savoir pour que je puisse clarifier!
x[0]
,x[0][0]
Etx[0][0][0]
ont différents types. Ils ne peuvent pas être comparés. Que voulez-vous dire!=
?