16

Considering the following code, is it safe to do pointer arithmetic on nullptr?

I assume adding any offsets to a nullptr results in another nullptr, so far MSVC produce results as I expected, however I am a bit unsure about whether using nullptr like this is safe:

float * x = nullptr;

float * y = x + 31; // I assume y is a nullptr after this assigment

if (y != nullptr)
{
  /* do something */
}
2
  • 1
    This is not what happens with clang and gcc, float* a = nullptr; assert(a==nullptr); a++; assert(a!=nullptr); . Adding something to nullptr doesn't result in nullptr with these compiles. I don't know if it is UB. Commented Dec 6, 2018 at 5:08
  • One short remark since no answer contains that: In practice, pointers are memory addresses. If you add an offset 31 to the null pointer naively, you obtain a pointer that points to the memory address 31. That's not the null pointer. The compiler is allowed to do exactly this. If null pointer + offset was defined to be the null pointer, the compiler would have to add some conditional jump there. Since the committee cares about efficiency, the standard does not mandate what happens when you add a non-zero offset to the null pointer. Commented Mar 1, 2019 at 8:36

5 Answers 5

15

You didn't define what "safe" means to you, but regardless, the code you propose has undefined behaviour. Pointer arithmetic is only allowed on pointer values that point into an array object, or perhaps to one-past-the-end of an array. (Non-array objects are considered an array of one element for the purpose of this rule.)

Since the null pointer is never the address of an object or one past an object, your code can never have well-defined behaviour.

Sign up to request clarification or add additional context in comments.

5 Comments

int* a; a++; is UB even if I dont dereference the pointer? Can you give a reference for that?
@tobi303: There's no reference for it, because the standard doesn't have to explicitly state that it's undefined. [expr.add]/5 defines the behavior of pointer+integer only for pointers to arrays (or pointer-to-object, which acts as an array of 1). If the pointer does not point to an array, then by definition the behavior is undefined (except in the case of adding 0, which [expr.add]/8 defines for all pointers).
@tobi303 UB doesn't mean "crash", it means "we did not define what this does". As it happens, compilers can aggressively optimize and detect UB and cause your program to behave extremely unexpectedly. One school of optimization is "as UB can not occur in a well formed program, any chain of logic that leads to UB can be safely eliminated as a possibility, up to and including skipping explicit if checks in your code". In short, UB can lead to time travel bugs, where code far away from the UB behaves in ways that do not match the code you wrote.
@NicolBolas thanks. something like [expr.add]/5 is what I meant when asking for a reference
@Yakk I know (more or less) what UB means, I just wasnt aware that int* a;a++ is UB until 1 hour ago
12

Is it safe to do pointer arithmetic on nullptr?

C++ defines two kind of operations on nullptr. For:

float *x = nullptr;
float *y = nullptr;
  1. x +/- 0 = x

  2. x - y = 0 (x and y have the same type)

You cannot make an assumption about what is not defined, so you shouldn't do it.

3 Comments

Actually, there's a third operation defined as well : x==y. Seems trivial, but it really means that there is just one null pointer value.
An example for x + 0: data() + size() is always valid for a vector even if it's empty in which case data() may or may not return null pointer.
6

Addign 0 to nullptr has well defined behavior and gives you nullptr back.

Adding anything else to nullptr has undefined behavior.

[expr.add]/4 has

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]), 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.

The first bullet point covers adding zero, the second deals with having an array, and the last bullet covers everything else.

Since we never have an array we can ignore the second bullet and just deal with the first and third. That gives us adding zero is defined behavior and adding any other value has undefined behavior.

Comments

2

... is it safe to do pointer arithmetic on nullptr?

No, arithmetic on the nullptr is not well defined since it is itself not a pointer type (but conversions to NULL values of all pointer types exist).

See here;

std::nullptr_t is the type of the null pointer literal, nullptr. It is a distinct type that is not itself a pointer type or a pointer to member type.


In general, arbitrary pointer arithmetic (even on the NULL value) is almost certainly going to cause problems - you didn't allocate that memory - it is not yours to attempt to read or write to.

For comparison purposes (e.g. one past the end), you will be fine, but otherwise the code you have will result in undefined behaviour.

For further reading, see Wikipedia on undefined behavior.

1 Comment

I'm not sure about the logic in your second paragraph: pointer arithmetic doesn't cause reading from or writing to memory. Memory has nothing to do with the OP's problem.
1

No, adding an offset to a nullptr does not result in a nullptr. This is undefined behavior.

1 Comment

You are correct that adding a non-zero offset does not result in a nullptr. However, adding/subtracting zero to/from a null pointer ARE well defined, and result in a null pointer (this is one specific difference between C and C++ - in C this is undefined).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.