#include <iostream>
using namespace std;
int main() {
int arr[5] = {5, 8, 1, 3, 6};
int len = *(&arr + 1) - arr;
cout << "The length of the array is: " << len;
return 0;
}
For the code above, I don't quite understand what these two pieces of codes are doing:
*(&arr + 1)
and
*(&arr)
&arr
Could someone explains? Because when I run the following two codes, I get the same output for the following:
&arr
(I think this point to the address of the first element of arr)
*(&arr)
then I don't quite understand what this do, what does the symbol *
do to &arr
(i.e. to the address here)?, because the two outputs are the same when I run them
and finally what is it exactly happening when an integer say 1 is added to the address by this code here:
&arr + 1
This is a mine field, but I'll give it a try:
&arr
returns a pointer to an int[5]
+ 1
steps the pointer one int[5]
*(&arr + 1)
dereferences the result back to an int(&)[5]
*(&arr + 1) - arr
does pointer arithmetics after the two int[5]
's have decayed to int
pointers, returning the diff between the two int
pointers, which is 5
.Rewritten to make it a bit clearer:
int arr[5] = {5, 8, 1, 3, 6};
int (*begin_ptr)[5] = &arr + 0; // begin_ptr is a int(*)[5]
int (*end_ptr)[5] = &arr + 1; // end_ptr is a int(*)[5]
// Note:
// begin_ptr + 1 == end_ptr
// end_ptr - begin_ptr == 1
int (&begin_ref)[5] = *begin_ptr; // begin_ref is a int(&)[5]
int (&end_ref)[5] = *end_ptr; // end_ref is a int(&)[5] UB here?
auto len = end_ref - begin_ref; // the array references decay into int*
std::cout << "The length of the array is: " << len << '\n'; // 5
I'll leave the question if it's UB or not open but referencing an object before the referenced storage has been allocated does look a bit suspicious.
Example:
int arr[] = {1, 2, 3, 4, 5, 6};
int size = *(&arr + 1) - arr;
Here the pointer arithmetic does its part. We don’t need to explicitly convert each of the locations to character pointers.
&arr
==> Pointer to an array of 6 elements.
[See this for difference between &arr
and arr]
(&arr + 1)
==> Address of 6 integers ahead as
pointer type is pointer to array
of 6 integers.
*(&arr + 1)
==> Same address as (&arr + 1), but
type of pointer is "int *".
*(&arr + 1) - arr
==> Since *(&arr + 1) points
to the address 6 integers
ahead of arr, the difference
between two is 6.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With