Para comprender este truco, primero debe comprender la diferencia del puntero, es decir, ¿qué sucede cuando se restan dos punteros que apuntan a elementos de la misma matriz ?
Cuando se sustrae un puntero de otro, el resultado es la distancia (medida en elementos de la matriz) entre los punteros. Entonces, si p
apunta a[i]
y q
apunta a[j]
, entonces p - q
es igual ai - j
.
C11: 6.5.6 Operadores aditivos (p9):
Cuando se restan dos punteros , ambos apuntarán a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz; El resultado es la diferencia de los subíndices de los dos elementos de la matriz . [...]
En otras palabras, si las expresiones P
y Q
apuntan, respectivamente, a los elementos i
-th y j
-th de un objeto de matriz, la expresión (P)-(Q)
tiene el valori−j
siempre que el valor se ajuste a un objeto de tipo ptrdiff_t
.
Ahora espero que esté al tanto de la conversión del nombre de la matriz a puntero, se a
convierte en puntero al primer elemento de la matriz a
. &a
es la dirección de todo el bloque de memoria, es decir, es una dirección de matriz a
. La siguiente figura lo ayudará a comprender ( lea esta respuesta para obtener una explicación detallada ):
Esto le ayudará a comprender por qué a
y &a
tiene la misma dirección y cómo (&a)[i]
es la dirección de la matriz (del mismo tamaño que la de a
).
Entonces, la declaración
return (&a)[n] - a;
es equivalente a
return (&a)[n] - (&a)[0];
y esta diferencia dará el número de elementos entre los punteros (&a)[n]
y (&a)[0]
, que son n
matrices de cada uno de los n
int
elementos. Por lo tanto, los elementos de la matriz total son n*n
= n
2 .
NOTA:
C11: 6.5.6 Operadores aditivos (p9):
Cuando se restan dos punteros, ambos apuntarán a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz ; El resultado es la diferencia de los subíndices de los dos elementos de la matriz. El tamaño del resultado está definido por la implementación , y su tipo (un tipo entero con signo) se ptrdiff_t
define en el <stddef.h>
encabezado. Si el resultado no es representable en un objeto de ese tipo, el comportamiento es indefinido.
Dado que (&a)[n]
ni apunta a elementos del mismo objeto de matriz ni a uno más allá del último elemento del objeto de matriz, (&a)[n] - a
invocará un comportamiento indefinido .
También tenga en cuenta que es mejor cambiar el tipo de función de retorno p
a ptrdiff_t
.