C is a low-level language which trusts you to ensure that the code you write is safe. Unlike other higher-level languages, there are no checks at run time or compile time.
Bearing that in mind, in this case you have allocated memory for one integer (which is likely to be four bytes and not 1 byte.) Malloc gives you back a pointer which does not contain any information about the size of the block you have allocated.
ptr[0] = 5
is equivalent to writing
*ptr = 5
Note that in C the first element of an array is at 0 not 1.
There are no checks that ptr
points to a valid block of memory.
Similarly when you write
ptr[10] = 5
that is equivalent to writing
*(ptr+10) = 5
This is undefined behaviour in this context and the compiler and runtime are permitted to do anything at all including produce the result you intend!
As to how this has worked, it is likely that the heap from which the integer was allocated contains enough space past the allocated space that you can write to without causing an access violation.
In a real program that space could be completely unused so there are no apparent ill effects (some of the time) or it could be in use by other code in the program or by the runtime to track allocations in the heap.
The lack of run time checks makes C very powerful and efficient but it also makes it easy to write code that is erratic or unsafe.