2

ISO IEC 14882-2011 §5.7/5 States:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

This section is used here on stackoverflow from time to time. For instance to argue why the increment of a pointer to nullptr is UB like here. It is then interpreted as, having a pointer that does not point to an element of an array object. Is undefined behaviour.

However, when I read this I understood it to refer to the evaluation of the pointer being UB. Which would mean that having such a pointer is well defined behaviour. And the behaviour becomes undefined when one tries to dereference it.

Which would mean that for example, incrementing a valid pointer beyond the array boundary is legal. Decrementing it again afterwards is legal. And since the pointer will then be the same value as before the increment, the evaluation is legal too.

Which of the two is the case?

Community
  • 1
  • 1
laurisvr
  • 2,724
  • 6
  • 25
  • 44
  • Which part of that quote is unclear? When you increment it, the pointer doesn't point to any element of any array, so "otherwise, the behaviour is undefined". So the increment gives UB, whatever you do later. – Mike Seymour May 21 '15 at 09:23
  • @molbdino That is not what I'm saying, I have updated my question to explain my point more clearly. – laurisvr May 21 '15 at 09:24

3 Answers3

4

The paragraph you're quoting refers to pointer arithmetic, not to evaluation of pointers.

It states that the only time pointer addition p + i is defined is if
(treating subtraction of i as equivalent to addition of -i)

  1. p points to an element of an array object or one past the last element, and
  2. p + i points to an element of the same array object, or one past the last element

If p isn't a pointer to an array element or "one past the end" - for instance if it is the null pointer or "two past the end" - the behaviour is undefined.
You don't need to dereference the result to cause undefined behaviour - the effect of the addition itself is undefined.

That is to say

int p[1] = {0};
int *q = p;  // OK
q = q + 1;   // OK - one past the end
int *r = q + 1;   // Undefined behaviour
r = r - 1;   // Doesn't make r valid or the program un-undefined

and likewise

int *p = nullptr;
p++; // Undefined
p--; // Still undefined
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • For purposes of that paragraph, may a `char` be regarded as a single-element array of `char`? For example, if one has a method which given a `char*` and a length, outputs `length` characters, would it be legitimate to pass a `char` variable to such a method along with a `length` of one, even if the method would increment the passed-in pointer after use? – supercat May 21 '15 at 21:17
  • @supercat I believe there's a paragraph somewhere in the standard about how a pointer to one `T` is usually considered equivalent to a pointer to the first element of a one-element array. – molbdnilo May 22 '15 at 08:18
3

"The evaluation" means the evaluation of the additive operation; thus UB would not occur for (say) static_cast<int*>(nullptr) + 1 within a non-evaluated context (sizeof, decltype, etc).

It does not mean "the evaluation of the pointer", and certainly not dereferencing it; if the standard had intended that interpretation, it would have said so.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
0

Incrementing then decrementing a null pointer is still undefined behaviour. When UB occurs, anything can happen, so this would be a valid sequence of an events:

  1. Increment null pointer. Undefined behaviour, so we'll set the pointer to 0xDEADBEEF because we can.
  2. Decrement pointer. Also undefined behaviour unless 0xDEADBEEF happens to be in a valid array after the first element.
  3. Dereference pointer. Issue forth nasal demons.
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Technically the nasal demons could come at any time, even before point 1. See [Undefined behavior can result in time travel (among other things, but time travel is the funkiest)](https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633) – Mark Ransom Aug 12 '22 at 00:21