From Newsgroup: comp.lang.c
Tim Rentsch <
tr.17687@z991.linuxsc.com> writes:
NS <ns@2b.here> writes:
Can all the values of a signed int be represented in an unsigned
int (or signed long in an unsigned long, etc.)?
Obviously not. Negative values cannot be represented in unsigned types.
But I don't think that's what NS meant.
I believe it follows from the *current* rules (C23) that the number
of representable values in signed int is exactly the same as the
number of representable values in unsigned int. It also follows
that each possible value of type signed int yields a unique value
when converted to unsigned int. (The reverse conversion is still implementation-defined.)
That wasn't the case in C17 and earlier. It was allowed, for
example, for signed int and unsigned int to have the same size,
with signed int having no padding bits and unsigned int having one
(in place of the sign bit). Thus you could have INT_MAX==UINT_MAX.
Such implementations were quite unusual, which presumably is why the
committee was able to make them non-conforming in C23.
[...]
It doesn't, because integer types (other than unsigned char) are
allowed to have padding bits, and unsigned types may have more
padding bits than signed types have.
Neither unsigned char nor signed char is allowed to have padding
bits, going back at least to C99. (I believe C99 is when the concept
of padding bits was introduced.) This implies that plain char also
is not allowed to have padding bits)
[...]
So, is it actually portable to represent signed integers as
unsigned?
Not fully portable, no. If it's important that this be true then
somewhere there should be a test that INT_MAX < UINT_MAX, etc.
(Note that as of C23 there are different rules, and indeed the newer
standard requires, IIUC, that unsigned types have the same number of
padding bits as their corresponding signed types, and consequently
that INT_MAX < UINT_MAX, etc.)
Note that C23 is the current ISO C standard, and C23 with extensions
is the default dialect for recent releases of gcc and clang.
Of course earlier editions are still relevant.
I believe you're correct about the change in requirements
for C23. Most obviously, C23 requires 2's-complement for all
signed types (prior editions also allowed sign-and-magnitude and ones'-complement).
N3220 6.2.6.2p2 says:
For signed integer types, the bits of the object representation
shall be divided into three groups: value bits, padding bits,
and the sign bit. If the corresponding unsigned type has width
N, the signed type uses the same number of N bits, its *width*,
as value bits and sign bit.
--
Keith Thompson (The_Other_Keith)
Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
--- Synchronet 3.22a-Linux NewsLink 1.2