It works because sometimes undefined behaviour actually does work. That still doesn't make it a good idea because it's not guaranteed to work.
What's likely happening under the covers is that the realloc
call is not changing anything at all because you've asked for a small reduction in a block that's already insignificantly small anyway.
Many memory allocation functions have a certain resolution which they allocate to, such as always a multiple of sixteen bytes. So, in that case, whether you asked for three four-byte pointers or four four-byte pointers, you'll always get a sixteen-byte chunk (plus overhead). It also means that, if you tell it to reduce your sixteen-byte chunk to a twelve-byte chunk, it's probably smart enough to just leave it alone.
You can check this by printing out the pointer just before and just after the realloc
- it's likely to be exactly the same value.
So it just leaves the memory alone which is why, when you access the fourth element of the array, it's still set up as before.
But, as stated, this is an implementation detail that is not guaranteed, so you should not rely on it. Ever!