As verbose said, this yields undefined behavior. A bit more precision follows.
5.2.1/1 says
[...] The expression E1[E2] is identical (by definition) to *((E1)+(E2))
Hence, val[i]
is equivalent to *((val)+i))
. Since val
is an array, the array-to-pointer conversion (4.2/1) occurs before the addition is performed. Therefore, val[i]
is equivalent to *(ptr + i)
where ptr
is an int*
set to &val[0]
.
Then, 5.7/2 explains what ptr + i
points to. It also says (emphasis are mine):
[...] 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.
In the case of ptr + i
, ptr is the pointer operand and the result is ptr + i
. According to the quote above, both should point to an element of the array or to one past the last element. That is, in the OP's case ptr + i
is a well defined expression for all i = 0, ..., 10
. Finally, *(ptr + i)
is well defined for 0 <= i < 10
but not for i = 10
.
Edit:
I'm puzzled to whether val[10]
(or, equivalently, *(ptr + 10)
) yields undefined behavior or not (I'm considering C++ not C). In some circumstances this is true (e.g. int x = val[10];
is undefined behavior) but in others this is not so clear. For instance,
int* p = &val[10];
As we have seen, this is equivalent to int* p = &*(ptr + 10);
which could be undefined behavior (because it dereferences a pointer to one past the last element of val
) or the same as int* p = ptr + 10;
which is well defined.
I found these two references which show how fuzzy this question is:
May I take the address of the one-past-the-end element of an array?
Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?