I'm talking about the case that both int and unsigned char are 16
bits, and to be honest I'm still not convinced that this is false.
Your underlying point is right; you just stated it incorrectly. The
problem occurs when not all values of unsigned char are in the range
of int.
The value returned by getc() is either the next character from the
input stream, interpreted as an unsigned char and converted to int, or
the value EOF (which must be negative and is typically -1).
On most systems, all values of type unsigned char can be converted to
int without changing their numeric value.
If both int and unsigned char are 16 bits, then (a) the conversion
from unsigned char to int is implementation-defined for values
numerically greater than INT_MAX, and (b) some valid unsigned char
value might be converted to the value EOF.
You can work around (b) by checking feof() and ferror() after getc()
returns EOF. If both are false, then you can assume that you read a
legimate character (say, 0xFFFF) that happened to be converted to EOF
(or that there's a bug in the implementation's feof() or ferror()
function, which might be almost as likely). Most programmers don't
bother to worry about this possibility. As a result, some code will
likely break if ported to such a system (most likely a DSP, which
probably has a freestanding implementation anyway and thus needn't
support <stdio.h> at all) *if* it happens to read such a character.
(a) the implementation-definedness of the conversion, could be a more
serious problem. Given this problem, I can't think of a way to write
*really* portable code to read from a file.
fread() is likely to copy the input directly into an array of
characters, and thus probably won't run into the same problem -- but
fread() is defined to work by calling fgetc(), so the standard doesn't
guarantee that you won't run into exactly the same problem.
In my opinion, it would be reasonable for the standard to require
INT_MAX >= UCHAR_MAX for all hosted implementations.