fgetc
returns EOF
on an end-of-file or error condition.
Otherwise, it returns the character that was read, as an unsigned char
, converted to int
.
Suppose CHAR_BIT == 16
and sizeof (int) == 1
, and suppose the next character read has the value 0xFFFF. Then fgetc()
will return 0xFFFF converted to int
.
Here it gets a little tricky. Since 0xFFFF can't be represented in type int
, the result of the conversion is implementation-defined. But typically, the result will be -1, which is a typical value (in fact, the only value I've ever heard of) for EOF
.
So on such a system, fgetc()
can return EOF
even if it successfully reads a character.
There is no contradiction here. The standard stays that fgetc()
returns EOF
at end-of-file or on an error. It doesn't say the reverse; returning EOF
doesn't necessarily imply that there was an error or end-of-file condition.
You can still determine whether fgetc()
read an actual character or not by calling feof()
and ferror()
.
So such a system would break the typical input loop:
while ((c = fgetc()) != EOF) {
...
}
but it wouldn't (necessarily) fail to conform to the standard.
(with reference to the comment by blagovest), does C99 specify when the standard library is to be expected, or whether a conforming
implementation can implement part but not all of the standard
library?
A "hosted implementation" must support the entire standard library, including <stdio.h>
.
A "freestanding implementation" needn't support <stdio.h>
; only standard headers that don't declare any functions (<limits.h>
, <stddef.h>
, etc.). But a freestanding implementation may provide <stdio.h>
if it chooses.
Typically freestanding implementations are for embedded systems, often with no operating system.
In practice, every current hosted implementation I'm aware of has CHAR_BIT==8
. The implication is that in practice you can probably count on an EOF
result from fgetc()
actually indicating either end-of-file or an error -- but the standard doesn't guarantee it.