Um diesen Hack zu verstehen, müssen Sie zuerst den Zeigerunterschied verstehen, dh was passiert, wenn zwei Zeiger, die auf Elemente desselben Arrays zeigen, subtrahiert werden?
Wenn ein Zeiger von einem anderen subtrahiert wird, ist das Ergebnis der Abstand (gemessen in Array-Elementen) zwischen den Zeigern. Wenn also p
auf a[i]
und q
zeigt auf a[j]
, dann p - q
ist gleichi - j
.
C11: 6.5.6 Additive Operatoren (S. 9):
Wenn zwei Zeiger subtrahiert werden , zeigen beide auf Elemente desselben Array-Objekts oder auf einen nach dem letzten Element des Array-Objekts. Das Ergebnis ist die Differenz der Indizes der beiden Array-Elemente . [...].
Mit anderen Worten, wenn die Ausdrücke P
und Q
auf das i
-te bzw. das j
-te Element eines Array-Objekts verweisen , hat der Ausdruck (P)-(Q)
den Wert,i−j
sofern der Wert in ein Objekt vom Typ passt ptrdiff_t
.
Jetzt erwarte ich, dass Sie wissen, dass der Array-Name in einen Zeiger a
konvertiert und in einen Zeiger auf das erste Element des Arrays konvertiert wird a
. &a
ist die Adresse des gesamten Speicherblocks, dh es ist eine Adresse des Arrays a
. Die folgende Abbildung hilft Ihnen beim Verständnis ( lesen Sie diese Antwort für eine detaillierte Erklärung ):
Dies hilft Ihnen zu verstehen, warum a
und &a
hat die gleiche Adresse und wie (&a)[i]
ist die Adresse des i- ten Arrays (von der gleichen Größe wie die von a
).
Also die Aussage
return (&a)[n] - a;
ist äquivalent zu
return (&a)[n] - (&a)[0];
und dieser Unterschied gibt die Anzahl der Elemente zwischen den Zeigern (&a)[n]
und an (&a)[0]
, die n
Arrays jedes n
int
Elements sind. Daher sind die gesamten Array-Elemente n*n
= n
2 .
HINWEIS:
C11: 6.5.6 Additive Operatoren (S. 9):
Wenn zwei Zeiger subtrahiert werden, zeigen beide auf Elemente desselben Array-Objekts oder auf einen nach dem letzten Element des Array-Objekts . Das Ergebnis ist die Differenz der Indizes der beiden Array-Elemente. Die Größe des Ergebnisses ist implementierungsdefiniert und sein Typ (ein vorzeichenbehafteter Integer-Typ) ist ptrdiff_t
im <stddef.h>
Header definiert . Wenn das Ergebnis in einem Objekt dieses Typs nicht darstellbar ist, ist das Verhalten undefiniert.
Da (&a)[n]
weder auf Elemente desselben Array-Objekts noch auf Elemente hinter dem letzten Element des Array-Objekts verweist, (&a)[n] - a
wird undefiniertes Verhalten aufgerufen .
Beachten Sie auch, dass es besser ist, den Rückgabetyp der Funktion p
in zu ändern ptrdiff_t
.