Hmm, je soupçonne que c'est quelque chose qui n'aurait pas fonctionné dans les premiers jours de C. C'est intelligent cependant.
Faire les étapes une par une:
&a
obtient un pointeur vers un objet de type int [5]
+1
obtient le prochain objet de ce type en supposant qu'il existe un tableau de ces
*
convertit efficacement cette adresse en pointeur de type vers int
-a
soustrait les deux pointeurs int, renvoyant le nombre d'instances int entre eux.
Je ne suis pas sûr que ce soit tout à fait légal (en cela je veux dire la langue-avocat juridique - cela ne fonctionnera pas dans la pratique), étant donné certaines opérations de type en cours. Par exemple, vous n'êtes "autorisé" à soustraire deux pointeurs que lorsqu'ils pointent vers des éléments du même tableau. *(&a+1)
a été synthétisé en accédant à un autre tableau, bien qu'un tableau parent, il n'est donc pas réellement un pointeur dans le même tableau que a
. De plus, alors que vous êtes autorisé à synthétiser un pointeur au-delà du dernier élément d'un tableau, et que vous pouvez traiter n'importe quel objet comme un tableau de 1 élément, l'opération de déréférencement ( *
) n'est pas "autorisée" sur ce pointeur synthétisé, même si elle n'a aucun comportement dans ce cas!
Je soupçonne que dans les premiers jours de C (syntaxe K&R, n'importe qui?), Un tableau s'est décomposé en un pointeur beaucoup plus rapidement, donc il *(&a+1)
pourrait ne renvoyer que l'adresse du pointeur suivant de type int **. Les définitions plus rigoureuses du C ++ moderne permettent définitivement au pointeur sur le type de tableau d'exister et de connaître la taille du tableau, et probablement les normes C ont emboîté le pas. Tout le code de fonction C ne prend que des pointeurs comme arguments, donc la différence technique visible est minime. Mais je ne fais que deviner ici.
Ce type de question de légalité détaillée s'applique généralement à un interpréteur C, ou à un outil de type lint, plutôt qu'au code compilé. Un interpréteur peut implémenter un tableau 2D comme un tableau de pointeurs vers des tableaux, car il y a une fonctionnalité d'exécution de moins à implémenter, auquel cas le déréférencement du +1 serait fatal, et même si cela fonctionnait, cela donnerait la mauvaise réponse.
Une autre faiblesse possible peut être que le compilateur C peut aligner le tableau externe. Imaginez s'il s'agissait d'un tableau de 5 caractères ( char arr[5]
), lorsque le programme s'exécute, &a+1
il invoque le comportement "tableau de tableau". Le compilateur peut décider qu'un tableau de tableau de 5 chars ( char arr[][5]
) est en fait généré comme un tableau de tableau de 8 chars ( char arr[][8]
), de sorte que le tableau externe s'aligne bien. Le code dont nous discutons indiquerait maintenant la taille du tableau comme 8, et non 5. Je ne dis pas qu'un compilateur particulier ferait certainement cela, mais il le pourrait.
&a + 1
ne pointe vers aucun objet valide, il est donc invalide.