Specifically, consider the following code:
uint8_t my_array[3] = { 1, 2, 3 };
uint8_t *my_array_a = my_array;
uint8_t *my_array_b = nullptr;
uint8_t *my_element1 = &my_array_a[0];
uint8_t *my_element2 = &my_array_b[0];
Note that neither operator&
nor operator*
are anything special for these types.
If this were C, the standard guarantees that my_array_b + 0
is not dereferenced during the computation of my_element2
(from ISO/IEC 9899:TC2, semantics of the &
operator):
Similarly, if the operand is the result of a
[]
operator, neither the&
operator nor the unary*
that is implied by the[]
is evaluated and the result is as if the&
operator were removed and the[]
were changed to an+
operator.
Does the C++ standard provide a similar guarantee (at least for the given scenario), or is it technically undefined behavior to compute my_element2
in this manner because it involves dereferencing nullptr
?
As far as I can tell, there is no hidden UB in the above snippet. Casting nullptr
to uint8_t*
is legal, and nullptr + 0
is explicitly defined as yielding nullptr
. Admittedly the sample is not very useful either, but we're rules-lawyering anyway.
This question is similar to Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?, but I am specifically interested in whether the &[]
-> +
conversion or a similar guarantee is also present in C++. The example in this post specifically does not perform any out-of-bounds indexing, but could still contain UB depending on whether the dereference actually happens or not.