Is incrementing/decrementing or adding an integer value to a pointer that is not pointing to an element in a sequence Undefined Behavior?

一曲冷凌霜 提交于 2020-12-29 03:51:25

问题


I know that pointers (to array element) and iterators can be incremented/decremented to walk a sequence of elements and can jump back-and-for elements in the sequence.

But what will happen if I increment a pointer to a single object or add to it an integer value? is it undefined behavior or it is OK but we cannot access that memory?

int x = 551;
int* p = &x;
++p;
--p;
std::cout << *p << '\n';

Because I've already read that we should not increment/decrement a pointer that doesn't point to an element in a sequence or an array for example.

So can someone explain what will happen and whether my example is OK (de-referencing pointer p)? Thank you!


回答1:


when pointer arithmetic applies to a pointer that points to an object, the pointer is considered to point to an array of that object type with only one element, as said in the standard.

An object that is not an array element is considered to belong to a single-element array for this purpose

In you example, the pointer p as if it point to int arr[1] = {551} So, the corresponding operation is similar to apply to a pointer that point to the arr. That means, ++p will make p point to the element arr[1] (hypothetical), and --p will make p point to the first element arr[0] again. So, in the last, de-referenceing pointer p is OK and does not result in any UB.




回答2:


Summary

Your program is not well-defined, even before getting to the dereference.

  • You may increment p once, resulting in a one-past-the-end pointer.
  • However, you may not decrement a one-past-the-end pointer.
    • Some iterator types permit such an operation, but this is not one of them (even though pointers are a kind of iterator).

Standardese

The rules in the standard relating to this capability are given in terms of arrays, but a note reminds us that a single object is considered to be an element of a single-element array for these purposes, citing the following passage which describes the meaning of your pointer:

[basic.compound/3]: [..] 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 object46 or the first byte in memory after the end of the storage occupied by the object, respectively. [..] 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. [..]

So, yes, you can safely "get" the one-past-the-end pointer per these rules. Unfortunately, you can't do much with it afterwards, since the pointer addition and subtraction rules are defined thus:

[expr.add/4]: When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.

  • If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
  • Otherwise, if P points to an array element i of an array object x with n elements ([dcl.array]),80 the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element i+j of x if 0≤i+j≤n and the expression P - J points to the (possibly-hypothetical) array element i−j of x if 0≤i−j≤n.
  • Otherwise, the behavior is undefined.

…and &x+1 is not an element of even the made-up array presented by the object x.

If it said "if P points to a (possibly-hypothetical) array element i of an array object x with n elements" then you'd be fine, because this would expand the behaviour given in the second bullet point to cover the one-past-the-end pointer (which is a "hypothetical array element of x" per the first quote). But it doesn't, so we fall through to the third bullet point, leaving your program with undefined behaviour.



来源:https://stackoverflow.com/questions/65172368/is-incrementing-decrementing-or-adding-an-integer-value-to-a-pointer-that-is-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!