This is undefined behavior. Undefined behavior means that anything can happen, including:
- segmentation fault
- no error at all
- inconsistent output
- formatting of hard drive
- ... (whatever)
To get a bit more formal, this is how the C++11 Standard defines undefined behavior:
behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of
behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior
ranges from ignoring the situation completely with unpredictable results, to behaving during translation or
program execution in a documented manner characteristic of the environment (with or without the issuance of
a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.
—end note ]
Concerning the reason why doing x[5]
is indeed undefined behavior, that's because x[5]
is equivalent to *(x + 5)
(see paragraph 8.3.4/6), and paragraph 5.3.1/1 about the unary operator *
specifies:
The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an
object type, or a pointer to a function type and the result is an lvalue referring to the object or function
to which the expression points. If the type of the expression is “pointer to T,” the type of the result is
“T.” [...]
But since x + 5
does not point to any object, and the above paragraph does not specify what the result of dereferencing such a pointer should be, the previously quoted sentence applies:
[...] Undefined behavior may be expected when this International Standard omits any explicit definition of behavior [...]
Which means that x[5]
is undefined behavior.