Welcome to the wonderful world of undefined behavior, where anything can happen!
The C spec says that in certain cases, the result of performing an operation results in what's called undefined behavior. This means that there are no guarantees whatsoever about what might happen when you perform those operations. The program might immediately crash. It might continue to run but with random memory regions corrupted. It might seem to cause no ill effects whatsoever. It might also cause the computer to gain sentience and compose poetry. (That last one is unlikely, but it's technically possible!)
In your case, if you try to access memory that you don't own (here, by reading off the end of a malloc
'ed array), the result is undefined behavior. On your system, it seems like walking off by one step in this particular case coincidentally happens to not cause any problems, but walking further than that does lead to a crash. The reason for this likely has to do with the particulars of your memory allocator and the specific machine you're on. This can be jarring if you're coming from a language like Python or Java where errors are more specified and better-defined.