Учитывая следующие факты:
Когда вы увеличиваете / уменьшаете указатель на целое значение X
, значение указателя увеличивается / уменьшается в X
раз количество байтов типа, на который указывает указатель.
Когда вы вычитаете 2 указателя одного и того же типа, результатом является разница между их удерживаемыми адресами, разделенная на количество байтов типа, на который указывают.
Когда вы ссылаетесь на массив только по его имени, он распадается в указатель на 1-й элемент массива.
Тип вашей переменной arr
: int[5]
, ie - массив из 5 int
с. &arr
возвращает указатель int[5]*
на arr
(технически он на самом деле написан как int(*)[5]
, но не будем беспокоиться об этом здесь, для простоты). Позволяет назвать этот указатель temp
ниже.
Затем + 1
увеличивает значение temp
на 1 int[5]
элемент. Другими словами, адрес, сохраненный в temp
, увеличивается на 1 * sizeof(int[5])
, или 1 * (sizeof(int) * 5)
, число байтов. Это фактически дает вам указатель int[5]*
до конца arr
(ie, до &arr[5]
). Элемент int[5]
физически не существует по этому адресу памяти, но создание указателя на него является законным для целей арифметики указателей c.
Разыменование temp
дает вам ссылка на int[5]
в конце arr
. Эта ссылка распадается в указатель int*
при передаче в operator-
.
В - arr
, ссылка на arr
распадается в int*
указатель на arr[0]
при передаче на operator-
.
Таким образом, с учетом этого кода:
int len = *(&arr + 1) - arr;
Что фактически совпадает с этим:
int len = &arr[5] - &arr[0];
Что фактически совпадает с этим:
int len = (<address of arr[5]> - <address of arr[0]>) / sizeof(int);
Таким образом, результат равен 5.