How does fread really work?

Roman Byshko picture Roman Byshko · Dec 21, 2011 · Viewed 76.9k times · Source

The declaration of fread is as following:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

The question is: Is there a difference in reading performance of two such calls to fread:

char a[1000];
  1. fread(a, 1, 1000, stdin);
  2. fread(a, 1000, 1, stdin);

Will it read 1000 bytes at once each time?

Answer

Keith Thompson picture Keith Thompson · Dec 21, 2011

There may or may not be any difference in performance. There is a difference in semantics.

fread(a, 1, 1000, stdin);

attempts to read 1000 data elements, each of which is 1 byte long.

fread(a, 1000, 1, stdin);

attempts to read 1 data element which is 1000 bytes long.

They're different because fread() returns the number of data elements it was able to read, not the number of bytes. If it reaches end-of-file (or an error condition) before reading the full 1000 bytes, the first version has to indicate exactly how many bytes it read; the second just fails and returns 0.

In practice, it's probably just going to call a lower-level function that attempts to read 1000 bytes and indicates how many bytes it actually read. For larger reads, it might make multiple lower-level calls. The computation of the value to be returned by fread() is different, but the expense of the calculation is trivial.

There may be a difference if the implementation can tell, before attempting to read the data, that there isn't enough data to read. For example, if you're reading from a 900-byte file, the first version will read all 900 bytes and return 900, while the second might not bother to read anything. In both cases, the file position indicator is advanced by the number of characters successfully read, i.e., 900.

But in general, you should probably choose how to call it based on what information you need from it. Read a single data element if a partial read is no better than not reading anything at all. Read in smaller chunks if partial reads are useful.