5

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.

molenzwiebel
  • 886
  • 6
  • 21
  • 5
    With `uint8_t *my_array_b = nullptr;` or `uint8_t *my_array_b = NULL;`, `my_array_b + 1` invokes undefined behavior in both languages. Pointer arithmetic is only valid within an array (objects count as arrays with 1 element) and 1 past the end. `nullptr` is not within an array. – mch Apr 03 '23 at 15:16
  • Deferencing a nullptr is always undefined behavior. The indexing operator can be used /overloaded to do many things and is not relevant to your question. – Pepijn Kramer Apr 03 '23 at 15:18
  • 2
    Related/Dupe: [Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?](https://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-the) – Jason Apr 03 '23 at 15:19
  • 1
    I am not sure if address-taking and indexing cancel out like in C, but I am pretty sure that pointer arithmetic on `nullptr` is undefined. – user3840170 Apr 03 '23 at 15:21
  • 1
    @PepijnKramer: Re “Deferencing a nullptr is always undefined behavior”: That is not the question. The C standard defines `&my_array_b[i]` such that there is no dereferencing. The question involves whether the C++ standard does the same. – Eric Postpischil Apr 03 '23 at 15:22
  • 2
    The C++ standard has a sentence about pointer arithmetic: “If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.” So `nullptr+0` is defined. So `&my_array_b[0]` would be defined if the C++ standard treats `&` with `[]` the same as the C standard does. But `&my_array_b[1]` is not. – Eric Postpischil Apr 03 '23 at 15:25
  • I've updated the post accordingly to consider index 0 instead. As far as I can tell, that should avoid most of the UB scenarios pointed out by @mch. Eric is correct in that I am more interested in the consideration of whether or not C++ provides a guarantee similar in nature to that in the C spec. – molenzwiebel Apr 03 '23 at 16:01
  • 2
    Reopened the question because after the edit the first linked duplicate doesn't apply anymore at all and the second one is specifically about forming references to dereferenced null pointer values, which is not what OP is suggesting in this question. – user17732522 Apr 03 '23 at 16:30
  • 1
    https://cplusplus.github.io/CWG/issues/232 – Language Lawyer Apr 03 '23 at 18:18

0 Answers0