The C standard does not allow an implementation to (spontaneously) move things in such a way as to invalidate an existing pointer. Perhaps there is an implementation that defragments the bunch, but I don't know any implementations that do.
I said "spontaneously" because calls to realloc() in your code can make the object move; therefore realloc returns a pointer. If the pointer returned by realloc is different from the original pointer, the original pointer (and any pointers that have its aliases) are invalid. But this is what you need to track in your own code.
Managed languages โโ(Java, C #, Python, independently) can (or cannot) handle heap fragmentation, adding an extra level of indirection and / or tracking pointers to the heap. Thus, the language runtime can update all pointers to an object X when X moves to another location. This will be taken care of by the garbage collection system.
It would be unusual if the C implementation provided a garbage collector and probably could not be executed in the standard way because of all the things you can (safely) do with pointers. Thus, the premise of your question that the heap may be defragmented by the implementation is invalid.
source share