Christopher Benson-Manica wrote:
Quote:
In a thread from substantially earlier this week,
>
Harald van D?k <truedfx@gmail.comwrote:
>
Quote:
>getchar does not work with plain chars, it works with unsigned chars. 163
>fits just fine in an unsigned char, so getchar is allowed to return 163.
>
Being rather pendantic, I decided to try to verify whether this was
true. I would appreciate knowing whether my reading of the Standard
is correct.
>
7.19.7.1 (as we all know) states that fgetc() (and thus its friends)
"obtains [a] character as an unsigned char converted to an int".
There is nothing in the Standard (that I was able to find) which
states that sizeof(int) may not be 1, so it occurred to me to ask, "Is
163 always representable as a signed int if sizeof(int) is 1?"
5.2.4.2.1 states that INT_MAX may not be less than 32767, so the
answer to that question appears to be "yes".
Right.
Quote:
On the other hand, I do not see anything in 5.2.4.2.1 which requires
that UCHAR_MAX not be greater than INT_MAX - which indeed it must be,
if sizeof(int) == 1, correct?
Correct. signed int has at least INT_MAX - INT_MIN + 1 distinct
representations, and if sizeof(int) == 1, that means unsigned char must be
capable of storing at least that many values. However, it is allowed to be
capable of storing even more.
Quote:
In such a case, fgetc() may return
UCHAR_MAX (right?), and so either fgetc() must work behind-the-scenes
magic to return a signed integer representing UCHAR_MAX, or invoke UB
by overflowing the signed type int. Both of these alternatives seem
ridiculous to me, so what am I missing?
The behaviour is not undefined for integer conversions of out-of-range
values, not even for the signed types. Either the result is
implementation-defined, or an implementation-defined signal is raised, see
6.3.1.3p3. The result is the same: fgetc need not or cannot be meaningful.
However, 7.19.2p3 states that
"A binary stream is an ordered sequence of characters that can transparently
record internal data. Data read in from a binary stream shall compare equal
to the data that were earlier written out to that stream, under the same
implementation. Such a stream may, however, have an implementation-defined
number of null characters appended to the end of the stream."
This requirement cannot be met by an implementation where the conversion of
out-of-range values results in a signal, or where the conversion of
out-of-range values cannot be reverted. So by my reading, only freestanding
implementations that do not provide the standard I/O functions at all are
allowed to define unsigned char and int in such ways.