First of all, just to clear something up, EOF
is not required to be specifically -1. The ISO C standard requires it to have a negative value.
Also note that the type char
can be signed or unsigned; that is implementation-defined.
The function fgetc
, getc
and getchar
can be used to process binary streams, not only text streams. Bytes have values from 0 to UCHAR_MAX
. The natural type for this range is unsigned char
. The return value of getc
couldn't be unsigned char
, because EOF
wouldn't be representable. It couldn't be signed char
either, because signed char
cannot hold the values from 0 to UCHAR_MAX
. So, a wider type is chosen: the type int
. On mainstream platforms, int
is wider than char
: it has a size of at least 2. And so it it is capable of representing some negative value that can be used for EOF
, and all the byte values in the range 0 to UCHAR_MAX
.
In some C implementations (for systems such as some DSP chips) this is not true: int
is one byte wide. That represents challenges. On such a C implementation, a range of valid byte values returned by getc
just has to be negative, and one of those values clashes with EOF
. Carefully written code can tell that this is the case: a value equal to EOF
was returned, yet the feof
and ferror
functions report false: the stream is not in error, and end-of-file has not occurred. Thus, the value which looks like EOF
is actually a valid byte.