This is very well explained in the classic book <i>The UNIX Programming Environment</i>, by Kernighan and Pike, in page 44:<p><i>Programs retrieve the data in a file by a system call ... called read. Each time read is called, it returns the next part of a file ... read also says how many bytes of the file were returned, so end of file is assumed when a read says "zero bytes are being returned" ... Actually, it makes sense not to represent end of file by a special byte value, because, as we said earlier, the meaning of the bytes depends on the interpretation of the file. But all files must end, and since all files must be accessed through read, returning zero is an interpretation-independent way to represent the end of a file without introducing a new special character.</i><p>Read what follows in the book if you want to understand Ctrl-D down cold.