Given the following facts:
When you increment/decrement a pointer by an integral value X
, the value of the pointer is increased/decreased by X
times the number of bytes of the type the pointer is pointing at.
When you subtract 2 pointers of the same type, the result is the difference between their held addresses, divided by the number of bytes of the type being pointed at.
When you refer to an array by its name alone, it decays into a pointer to the array's 1st element.
The type of your arr
variable is int[5]
, ie an array of 5 int
s. &arr
returns an int[5]*
pointer to arr
(technically, it is actually written like int(*)[5]
, but lets not worry about that here, for simplicity). Lets call this pointer temp
below.
Then, the + 1
increments the value of temp
by 1 int[5]
element. In other words, the address stored in temp
is increased by 1 * sizeof(int[5])
, or 1 * (sizeof(int) * 5)
, number of bytes. This effectively gives you an int[5]*
pointer to the end of arr
(ie, to &arr[5]
). No int[5]
element physically exists at that memory address, but it is legal to create a pointer to it, for purposes of pointer arithmetic.
Dereferencing temp
gives you a reference to an int[5]
at the end of arr
. That reference decays into an int*
pointer when passed to operator-
.
In - arr
, the reference to arr
decays into an int*
pointer to arr[0]
when passed to operator-
.
Thus, given this code:
int len = *(&arr + 1) - arr;
Which is effectively the same as this:
int len = &arr[5] - &arr[0];
Which is effectively the same as this:
int len = (<address of arr[5]> - <address of arr[0]>) / sizeof(int);
Thus, the result is 5.