Why doesn't the compiler complain? Because it's not required to. The language standard describes the circumstances that require a compiler to complain, and a mere array-index-out-of-bounds is not one of them.
Decent static analysis tools are capable of detecting this scenario for specific cases. The simple case of:
anArray = 0;
will likely be detected by most static analysis tools. But C and C++ compilers are not required to do so.
As for why the standard doesn't require them to... why should it?
Your particular scenario is only trivially detectable for two reasons:
The compiler has knowledge of the size of that array.
The index you are using is known by the compiler at compile time.
In real-world cases of index-out-of-bounds scenarios, one or both of these will usually not be true. And no, C++ does not in fact have ways of knowing what the length of an array is. Because you can do this:
int *arr = new int;
int *arr2 = arr + 5;
arr2 is just as much of an array as
arr. And yet, there is no way to determine how many elements are in
And even if you could... that wouldn't be something you would know at compile time. Accessing said length would be a runtime memory access. Once the array becomes an
int*, it's no longer an array; it's just a pointer, which you can access as though it were an array. The compiler no longer has certain knowledge of what gets stored there. So you've lost #1.
So there is no way that the compiler could complain in most of the real-world cases that are problematic.
The next, unasked, question is why doesn't the compiler emit runtime code to verify things like this? Because such runtime safety takes time, and by default C and C++ are not safe languages. By design, they are intended to achieve the fastest possible performance, even if that means that writing broken (or breakable) code is easier than writing correct code.
You can like it or hate it, applaud it or deride it. However you feel about it, that's the design ethic of the language(s).