From the standard (4.7) it looks like the conversion from int to unsigned int, when they both use the same number of bits, is purely conceptual:
If the de
"Destination type" refers to the type you're assigning/casting to.
The whole paragraph means a 32 bit unsigned int
converted to a 32 bit signed int
will stay as-is, given the value fits into the signed int
. If they don't fit, it depends on the implementation on what it does (e.g. truncate). That means it really depends on the implementation whether the bits stay or whether they're changed (there's no guarantee).
Or in other words: If the unsigned int
uses its most significant bit, the result is no longer predictable. Otherwise there's no change (other than changing the "name on the box").
You cannot assume anything.
The first quote doesn't state that the bitmask remains the same. It may be the same in two's complement, but not in one's complement or other representations.
Second, implementation-defined means implementation-defined, you can't assume anything in general.
In theory, the representation can be completely different after each conversion. That's it.
If you look at it in a realistic way things come more concrete. Usually, int's are stored in two's complement and signed->unsigned preserves the pattern as unsigned->signed does (since the value can be implementation-defined, the cheapest way is doing nothing).
int
is the destination type in this case. As you say 2^32-1 cannot be represented so in this case so it is implementation-specific. Although, I've only ever seen it preserve bit patterns.
EDIT: I should add that in the embedded world often whats done when one storage location needs multiple representations that are bit-for-bit identical we often use unions.
so in this case
union FOO {
int32_t signedVal;
uint32_t unsignedVal;
} var;
var
can be accessed as var.signedVal
to get the 32 bits stored as a signed int and var.unsignedVal
to get the 32 bits stored as an unsigned value. In this case bits will be preserved.