I was asking myself if these line of code could produce undefined behaviour in C and in C++.
I tried to answer to each point reading what the standard says about array subscripting (C 6.5.6 – 8). I didn’t posted the entire paragraph because it is pretty long.
Moreover, if the expression
Ppoints to the last
element of an array object, the expression(P)+1points one past the last element of the
array object, and if the expressionQpoints one past the last element of an array object,
the expression(Q)-1points to the last element of the array object. 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. If the result points one past the last element of the array >object, it
shall not be used as the operand of a unary*operator that is evaluated.
1 int a[10];
2 int b = a[9]; // ok
3 int c = a[10]; // UB
4 int* d = (a + 10); // ok
5 int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not deferenced), // UB in pre C99
6 int* f = &a[11]; // ok from C99, UB in pre c99
int* g = a;
7 int* h = g + 15; // ok
I think that the same aswers should be valid for C++
Are these lines valid in C and in C++, have I misunderstood the standard?
Neither 6 nor 7 are valid, because they do not perform pointer arithmetic inside an existing array (including the one-past-the-end pointer). Everything else is essentially correct.
In C only: Given that
a[i]is identical to*(a + i), and&*pis always justpwithout evaluating*p, 5 should always be fine, although you’re right that C89 does not specify this and this was only added in C99. (This is not true at all in C++, where operators can be overloaded and there is no mention of combining&and*.)From n1570 (draft to C11), in paragraph 8 of 6.5.6 Additive operators:
C++ contains very similar wording (e.g. C++11, 5.7/5).