Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is one-past-end pointer OK for non-array object types?

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?

like image 463
Ayxan Haqverdili Avatar asked Nov 30 '19 15:11

Ayxan Haqverdili


People also ask

Can a pointer point one past the end of an object?

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.

Can you reference past the last element in an array?

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.

Which pointer can point to any data type?

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.

Are all pointers arrays?

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.


1 Answers

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.

like image 66
StoryTeller - Unslander Monica Avatar answered Sep 19 '22 11:09

StoryTeller - Unslander Monica