Per capire questo hack, prima devi capire la differenza del puntatore, cioè cosa succede quando vengono sottratti due puntatori che puntano su elementi dello stesso array ?
Quando un puntatore viene sottratto da un altro, il risultato è la distanza (misurata in elementi dell'array) tra i puntatori. Quindi, se p
punta a a[i]
e q
punta a a[j]
, allora p - q
è uguale ai - j
.
C11: 6.5.6 Operatori additivi (p9):
Quando vengono sottratti due puntatori , entrambi devono puntare a elementi dello stesso oggetto array o uno oltre l'ultimo elemento dell'oggetto array; il risultato è la differenza dei pedici dei due elementi dell'array . [...].
In altre parole, se le espressioni P
e Q
puntano, rispettivamente, agli elementi i
-th e j
-th di un oggetto array, l'espressione (P)-(Q)
ha il valore ai−j
condizione che il valore si adatti a un oggetto di tipo ptrdiff_t
.
Ora mi aspetto che tu sia a conoscenza della conversione del nome dell'array in puntatore, che a
converte in puntatore al primo elemento dell'array a
. &a
è l'indirizzo dell'intero blocco di memoria, ovvero è un indirizzo di array a
. La figura seguente ti aiuterà a capire ( leggi questa risposta per una spiegazione dettagliata ):
Questo ti aiuterà a capire perché a
e perché &a
ha lo stesso indirizzo e come (&a)[i]
è l'indirizzo del mio array (della stessa dimensione di quello di a
).
Quindi, la dichiarazione
return (&a)[n] - a;
è equivalente a
return (&a)[n] - (&a)[0];
e questa differenza fornirà il numero di elementi tra i puntatori (&a)[n]
e (&a)[0]
, che sono n
array ciascuno di n
int
elementi. Pertanto, gli elementi dell'array totale sono n*n
= n
2 .
NOTA:
C11: 6.5.6 Operatori additivi (p9):
Quando vengono sottratti due puntatori, entrambi devono puntare a elementi dello stesso oggetto array o uno oltre l'ultimo elemento dell'oggetto array ; il risultato è la differenza dei pedici dei due elementi dell'array. La dimensione del risultato è definita dall'implementazione e il suo tipo (un tipo intero con segno) è ptrdiff_t
definito <stddef.h>
nell'intestazione. Se il risultato non è rappresentabile in un oggetto di quel tipo, il comportamento non è definito.
Poiché (&a)[n]
né punta a elementi dello stesso oggetto array né a uno oltre l'ultimo elemento dell'oggetto array, (&a)[n] - a
invocherà un comportamento indefinito .
Inoltre, è meglio cambiare il tipo di funzione di ritorno p
in ptrdiff_t
.