In C++ Primer, Chapter 2, \"Variables and Basic Types\", it says:
it is possible for a pointer to an object and a pointer one past the end of a different
It means that after
int a[] = { 1, 2 };
float b;
it's possible that (void *) &a[2] == (void *) &b
may compare as true.
&a[2]
(or equivalently, a+2
) is a pointer just past the end of a
, because the array only contains elements with indices 0 and 1.
Normally, out-of-range array indices are completely invalid (accessing a[2]
is not allowed, nor is even computing &a[3]
), but there is a special exception for computing the address just past the end of an array, because as it turned out, that is quite useful, for example when iterating over an array and you need an end value to know when to stop the loop.
"one past" means "+1 operation on the pointer". The following code generates:
0x7ffffcf6a848
0x7ffffcf6a84c
0x7ffffcf6a84c
As you can see, the address of "one past a", i.e., &a + 1
is the same as &b
.
int a = 2;
int b = 3;
cout<< &a << endl << &a + 1 << endl << &b <<endl;
Suppose you have an array, int foo[5] = {1,2,3,4,5};
. It's laid out in memory like this:
-----------
|1|2|3|4|5|
-----------
It's legal to have a pointer that points to any member of the array; but it's also legal for a pointer to point one past the end of the array (usually to signal that it has reached the end of the array when doing an STL algorithm using iterators) - although it isn't legal to dereference that pointer. Like so:
-------------
|1|2|3|4|5|?|
-------------
^ ^
| |
p q
p
is a pointer into the array; q
is a pointer one-past-the-end.
Now, suppose you also have an array const char bar[3] = "Hi";
. It's possible that the two arrays have been allocated next to each other in memory, like so:
<--foo---> <-bar->
-----------------
|1|2|3|4|5|H|i|0|
-----------------
^ ^
| |
p q
Then q
is both a one-past-the-end for foo
, and also pointing to the physical location for bar[0]
.