Чтобы понять этот хак, сначала нужно понять разницу в указателях, т. Е. Что происходит, когда два указателя указывают на элементы одного массива вычитаются ?
Когда один указатель вычитается из другого, результатом является расстояние (измеренное в элементах массива) между указателями. Итак, если p
указывает на a[i]
и q
указывает на a[j]
, тоp - q
равноi - j
.
C11: 6.5.6 Аддитивные операторы (p9):
Когда вычтены два указателя , оба должны указывать на элементы одного и того же объекта массива или один после последнего элемента объекта массива; Результатом является разница индексов двух элементов массива . [...].
Другими словами, если выражения P
и Q
указывают, соответственно, на i
-й и j
-й элементы объекта массива, выражение (P)-(Q)
имеет значениеi−j
при условии, что это значение соответствует объекту типа ptrdiff_t
.
Теперь я ожидаю, что вы знаете о преобразовании имени массива в указатель, a
преобразует указатель на первый элемент массива a
. &a
это адрес всего блока памяти, т.е. это адрес массива a
. Рисунок ниже поможет вам понять ( прочитайте этот ответ для подробного объяснения ):
Это поможет вам понять , что , почему a
и &a
имеет тот же адрес , и как (&a)[i]
это адрес I - го массива (такого же размера, как уa
).
Итак, утверждение
return (&a)[n] - a;
эквивалентно
return (&a)[n] - (&a)[0];
и эта разница будет давать количество элементов между указателями (&a)[n]
и (&a)[0]
, которые являются n
массивами каждого из n
int
элементов. Следовательно, все элементы массива равны n*n
= n
2 .
НОТА:
C11: 6.5.6 Аддитивные операторы (p9):
Когда вычтены два указателя, оба должны указывать на элементы одного и того же объекта массива или один после последнего элемента объекта массива ; Результатом является разница индексов двух элементов массива. Размер результата определяется реализацией , а его тип (целочисленный тип со знаком) ptrdiff_t
определяется в <stddef.h>
заголовке. Если результат не может быть представлен в объекте этого типа, поведение не определено.
Поскольку (&a)[n]
ни указатель на элементы одного и того же объекта массива, ни на один элемент после последнего элемента объекта массива (&a)[n] - a
не вызовет неопределенное поведение .
Также отметим , что, лучше изменить тип возвращаемого значения функции p
в ptrdiff_t
.