Is this valid C++?
int main()
{
int i = 0;
int* pi = &i;
++pi;
}
I know that one-past-end pointers are allowed for array types, but I'm not sure in this case. Does that code technically have undefined behavior?
it is possible for a pointer to an object and a pointer one past the end of a different object to hold the same address.
It is legal. According to the gcc documentation for C++, &array[5] is legal. In both C++ and in C you may safely address the element one past the end of an array - you will get a valid pointer.
Since void is nothing, it means that it can point to any block of memory, that contains any type of data. void * is rather a restricted type as one cannot dereference it and thus it cannot be used for pointer arithmetic.
Let's get the important stuff out of the way first: arrays are not pointers. Array types and pointer types are completely different things and are treated differently by the compiler.
Yes, it is okay. It is one of the four categories of values any pointer type may hold.
[basic.compound] (emphasis mine)
3 Every value of pointer type is one of the following:
- a pointer to an object or function (the pointer is said to point to the object or function), or
- a pointer past the end of an object ([expr.add]), or
- the null pointer value ([conv.ptr]) for that type, or
- an invalid pointer value.
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see [basic.stc]. — end note ] For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), a pointer past the end of the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical array element n of x and an object of type T that is not an array element is considered to belong to an array with one element of type T.
As you can see, array types are also mentioned here, with their hypothetical object past the end. And as the footnote in [expr.add] explains, the arithmetic to obtain a one-past-the-end pointer is meant to be valid too:
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose and a pointer past the last element of an array of n elements is considered to be equivalent to a pointer to a hypothetical array element n for this purpose.
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