No, the code should not (necessarily) give a segfault. A segfault occurs when you attempt to access a virtual memory page that is not allocated to your process.
The "heap" or "free store" is a region of virtual memory pages owned by your process. The malloc()
API sub-divides this region into blocks and returns a pointer to the block.
If you address beyond the end of the block to which you have a pointer, you will usually access memory that is part of the heap, but not part of your allocated block. In this way, you can corrupt other heap blocks or even the data structures which malloc()
uses to define the heap.
For more information on heap corruption, and methods to detect it in the debug version of your code, this is a great book:
Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs by Steve Maguire
An addendum for the pedantic: In rare cases, by accessing memory beyond the end of a heap block, you may access memory that is not part of the heap. In these cases, you may get the segmentation fault you expected. You might also corrupt some other data structure than the heap. It's really a matter of chance. However, the heap itself is very large compared to typical heap blocks, so 99% of the time code such as your example will corrupt the heap. The example you provide falls into that 99% case.