0

After RTFM, it is now somewhat unclear to me what I can really infer from the return value of fread()/fwrite() if the returned value is less than the number of requested elements.

Consider at first

nhave = fread(dst, 1, nwant, fp);

From the C17 standard (7.21.8.1/3):

The fread function returns the number of elements successfully read which may be less than nwant if a read error or end-of-file is encountered.

Hence, if nhave < nwant upon return, there could have been a read error or eof (but there could be other reasons as well). Since it's if and not only if, one cannot conclude feof(fp) if !ferror(fp)in this case. If !ferror(fp), it could still have been a successful read (of nhave bytes) according to the standard.

MSDN and cppreference.com have the same wording.

But then POSIX.1-2017:

Upon successful completion, fread() shall return the number of elements successfully read which is less than nwant only if a read error or end-of-file is encountered.

Hence, if nhave < nwant upon return, there must have been a read error or eof (there cannot be other reasons). Thus in this case, one can conclude feof(fp) if !ferror(fp). While being different from the specification in the C Standard, this behavior is not flagged as an extension to the C Standard in POSIX.

And from the fread(3) manual page on Linux (a POSIX-conforming platform):

If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).

Formally, this is the reverse (!) statement to that from POSIX.

Now consider fwrite(),

nhave = fwrite(src, 1, nwant, fp);

Let's start with POSIX.1-2017 here:

The fwrite() function shall return the number of elements successfully written, which may be less than nwant if a write error is encountered.

Hence, if nhave < nwant, there could (but need not) have been a write error. One cannot conclude ferror(fp)in this case but need to check.

MSDN and cppreference.com have the same wording.

However, according to the C17 standard (7.21.8.2/3), one can conclude more:

The fwrite function returns the number of elements successfully written, which will be less than nwant only if a write error is encountered.

Hence in this case, nhave < nwant does imply a write error and thus ferror(fp).

This is even more bizarre than in the case of fread() above since POSIX, Windows, and C++ are each supposed to follow the C standard.

So, what's going on here? Just sloppy wording? In particular and from a programmer's point of view:

Can I assume the POSIX wording for the return value of fread() (as given above) also for C/C++/Windows/..., i.e., does nhave < nwant imply a read error (and thus, ferror(fp)) or eof (and hence, feof(fp))?

Can I assume the C wording of the return value of fwrite() (as given above) also for C++/Windows/POSIX/..., i.e., does nhave < nwant imply a write error (and thus, ferror(fp))?

asked Jan 26, 2021 at 23:26
8
  • 2
    How is it bizarre? C specifies the possible results are in some set S. POSIX says the possible results are in some set T. T is a subset of S. So all results that conform to the POSIX specification also conform to the C specification. Why is there a question about "supposed to follow the C standard"? T conforms. The only discrepancy is that this is not noted as an extension. But I can see people viewing an extension as something that is a notable extra behavior, rather than simple narrowing of the possibilities... Commented Jan 27, 2021 at 0:17
  • ... For example, requiring int to be 32 bits is technically an extension of the C standard, but few people would call it that outside a formal mathematical context. Commented Jan 27, 2021 at 0:18
  • Did you observe behavior contrary to what is stated? Or are you simply confused with the wording of the documentation? Please clarify which one and update your post and title with your revised question. Commented Jan 27, 2021 at 0:31
  • @EricPostpischil: Because in case of fwrite() it's just the opposite of what you stated. The behavior specified in the C Standard is more strict than that mandated by POSIX and MSDN. Commented Jan 27, 2021 at 0:33
  • 3
    @smac Evidrnce of actual prgrams when making critcism of standards wording is not a requirement. The OP admitted a plausible reason is sloppy writing; "only if" and "if" being equivalent is sloppy, they have different meanings. What more, this question is tagged "language lawyer": it is aimed at understanding what standards say as much as what programs and implementations do. If you don't like discussing what standards say, don't comment, read or answer "language lawyer" tagged posts. Complaining they are talking about wording is like complaining a java tagged question talks about java. Commented Jan 27, 2021 at 1:02

1 Answer 1

4

So, what's going on here? Just sloppy wording?

I think you are parsing words too finely, which you can characterize as sloppy wording of the specifications if you prefer.

Consider fread() first. C17 says,

The fread function returns the number of elements successfully read, which may be less than nmemb if a read error or end-of-file is encountered.

I grant that that wording does not explicitly state that error or end-of-file are the only reasons for fewer items to be read than were requested, but if that were not the intention then why would error and end-of-file conditions be mentioned at all?

The C17 wording for fwrite is unambiguous:

The fwrite function returns the number of elements successfully written, which will be less than nmemb only if a write error is encountered.

Comparing the two, one could follow two different lines of reasoning:

  1. That the two functions are meant to be analogous, so the ambiguous wording for fread should be interpreted in the same "only if" sense as is explicitly specified for fwrite, OR

  2. That the same wording would have been used for the two if the same interpretation had been intended.

I find the first more persuasive, especially given that it also explains why the fread docs even mention error and end of file conditions. I am entirely prepared to accept that despite the committee's best intentions, the language of the specification is less than perfect.

answered Jan 27, 2021 at 1:02
Sign up to request clarification or add additional context in comments.

1 Comment

The ultimate goal of fread() is to read a given number of data elements of a given size. Hence, an implementation should only return prematurely on EOF or if an error occurred. This would favor your first interpretation. But then again, still somewhat speculative.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.