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))?
1 Answer 1
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
freadfunction returns the number of elements successfully read, which may be less thannmembif 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
fwritefunction 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:
That the two functions are meant to be analogous, so the ambiguous wording for
freadshould be interpreted in the same "only if" sense as is explicitly specified forfwrite, ORThat 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.
intto be 32 bits is technically an extension of the C standard, but few people would call it that outside a formal mathematical context.