What you're missing is that the compiler isn't required to catch this case, and often won't. This is undefined behavior, which means that there are no requirements as to what the implementation does, and it's your job to avoid it. Typically, the compiler will just compile whatever it sees in case of undefined behavior, and the sometimes reasonable behavior that comes out can be confusing.
In this case, you stored a memory address in numeros
, and in the next statement referenced *(numeros + 900)
, which given the usual int
size would be 3600 bytes after the memory address. The compiler generated the code for the reference. Considering that this is undefined behavior, the compiler was perfectly correct to do so, or for that matter to write an insulting email to you or your mother; the Standard specifies nothing. It could, of course, detect this and give you a run-time error saying "Address out of bounds at line 7", but unfortunately none of the compilers I've used give you that option.
This is one of the trickier parts of C programming: making sure your program is well-defined.