Search code examples
ciofread

c - read() and fread() return values


good people of SO!

I have rather a theoretical question. At read() manpages i read the following:

   On error, -1 is returned, and errno is set appropriately.  In this
   case, it is left unspecified whether the file position (if any)
   changes.

While in fread() ones the correspondend fragment is the following:

   If an error occurs, or the end of the file is
   reached, the return value is a short item count (or zero).
   ...
   **fread()** does not distinguish between end-of-file and error, and
   callers must use feof(3) and ferror(3) to determine which occurred.

My question - is there any practical reason why read() do distinguish EOF and an error, and fread() not?

Thank you in advance!


Solution

  • The return value of fread is size_t. This is an unsigned type, so there's no available value that would be different from a value indicating how many items were read.

    Furthermore, fread() may need to call read() multiple times to read all the items that were requested. If an error or EOF occurs on one of the later reads, it should still return all the items that were successfully read before that. So it returns that item count.

    Since the reason for the short item count can't be encoded in the return value, it would need to have some other way of returning this. It's easier to just leave that to the caller, using feof() and ferror().

    If read() encounters an error after a partial read, this is usually treated as success. It returns the length of the data that was read. The caller doesn't find out about the error until the next call to read(), when it returns -1 and sets errno.

    A signal can also cause read() to return early. In this case it returns -1 and sets errno == EINTR. The kernel keeps the partial read in a buffer so it can be returned on the next call.