4

When reading the documentation for fread here, it explains that the two arguments after the void *ptr are multiplied together to determine the amount of bytes being read / written in the file. Below is the function header for fread given from the link:

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

My question is, other than the returned value from the function, is there really a behavior or performance difference between calling each of these:

// assume arr is an int[SOME_LARGE_NUMBER] and fp is a FILE*
fread(arr, sizeof(arr), 1, fp);
fread(arr, sizeof(arr) / sizeof(int), sizeof(int), fp);
fread(arr, sizeof(int), sizeof(arr) / sizeof(int), fp);
fread(arr, 1, sizeof(arr), fp);

And which one would generally be the best practice? Or a more general question is, how do I decide what to specify for each of the arguments in any given scenario?

EDIT

To clarify, I am not asking for a justification of two arguments instead of one, I'm asking for a general approach on deciding what to pass to the arguments in any given scenario. And this answer that Massimiliano linked in the comments and cited only provides two specific examples and doesn't sufficiently explain why that behavior happens.

Community
  • 1
  • 1
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • The *behavior* is different, but since you don't check for errors you cannot see it. *Performance* relies on the specific library in use. In the marked-as-duplicated it is stated that "fread internally works through `fputc`", which may have been true originally but which is hard to believe to hold in the 21st century. – Jongware Apr 25 '15 at 06:36
  • Then take a look at the second answer in the link ;) – Massimiliano Apr 25 '15 at 06:38
  • @Massimiliano that only specifies two special cases, and as commenters noted, that answer could use a lot of improvement. – Patrick Roberts Apr 25 '15 at 06:40
  • In that case, I would try to improve the existing answer, instead of duplicating it. Just my 2 cents, though. – Massimiliano Apr 25 '15 at 06:43

1 Answers1

4

There is a behavior difference if there is not enough data to satisfy the request. From the page you linked to:

The total number of elements successfully read are returned as a size_t object, which is an integral data type. If this number differs from the nmemb parameter, then either an error had occurred or the End Of File was reached.

So if you specify that there is only one element of size sizeof(arr), and there is not enough data to fill arr, then you won't get any data returned. If you do:

fread(arr, sizeof(int), sizeof(arr) / sizeof(int), fp);

then arr will be partially filled if there is not enough data.

The third line of your code most naturally fits the API of fread. However, you could use one of the other forms if you document why you are not doing the normal thing.

Craig S. Anderson
  • 6,966
  • 4
  • 33
  • 46