Pour comprendre ce hack, vous devez d'abord comprendre la différence de pointeur, c'est-à-dire que se passe-t-il lorsque deux pointeurs pointant vers des éléments du même tableau sont soustraits?
Lorsqu'un pointeur est soustrait d'un autre, le résultat est la distance (mesurée en éléments du tableau) entre les pointeurs. Donc, si p
pointe vers a[i]
et q
pointe vers a[j]
, alors p - q
est égal ài - j
.
C11: 6.5.6 Opérateurs additifs (p9):
Lorsque deux pointeurs sont soustraits , les deux doivent pointer vers des éléments du même objet tableau, ou un après le dernier élément de l'objet tableau; le résultat est la différence des indices des deux éléments du tableau . [...].
En d'autres termes, si les expressions P
et Q
pointent respectivement vers les i
-ème et j
-ème éléments d'un objet tableau, l'expression (P)-(Q)
a la valeur ài−j
condition que la valeur tienne dans un objet de type ptrdiff_t
.
Maintenant, je m'attends à ce que vous soyez conscient de la conversion du nom du tableau en pointeur, a
convertit en pointeur vers le premier élément du tableau a
. &a
est l'adresse du bloc mémoire entier, c'est-à-dire que c'est une adresse de tableau a
. La figure ci-dessous vous aidera à comprendre ( lisez cette réponse pour une explication détaillée ):
Cela vous aidera à comprendre pourquoi a
et &a
a la même adresse et comment (&a)[i]
est l'adresse du i ème tableau (de même taille que celle de a
).
Donc, la déclaration
return (&a)[n] - a;
est équivalent à
return (&a)[n] - (&a)[0];
et cette différence donnera le nombre d'éléments entre les pointeurs (&a)[n]
et (&a)[0]
, qui sont des n
tableaux de chacun des n
int
éléments. Par conséquent, le total des éléments du tableau est n*n
= n
2 .
REMARQUE:
C11: 6.5.6 Opérateurs additifs (p9):
Lorsque deux pointeurs sont soustraits, les deux doivent pointer vers des éléments du même objet tableau, ou un après le dernier élément de l'objet tableau ; le résultat est la différence des indices des deux éléments du tableau. La taille du résultat est définie par l'implémentation et son type (un type entier signé) est ptrdiff_t
défini dans l'en- <stddef.h>
tête. Si le résultat n'est pas représentable dans un objet de ce type, le comportement n'est pas défini.
Puisque (&a)[n]
ni ne pointe vers des éléments du même objet de tableau ni un après le dernier élément de l'objet de tableau, (&a)[n] - a
invoquera un comportement indéfini .
Notez également que, mieux vaut changer le type de retour de la fonction p
en ptrdiff_t
.