For an unsigned integer type, the value -1 is out of range and cannot be represented in a variable of that type. If you try to assign -1 to an unsigned int
a conversion occurs according to the rules of the C standard.
The conversion of a signed value to an unsigned integer type is specified in section 6.3.1.3p2 of the C standard:
Otherwise, if the new type is unsigned, the value is
converted by repeatedly adding or subtracting one more than
the maximum value that can be represented in the new type
until the value is in the range of the new type.60
...
60) The rules describe arithmetic on the mathematical value, not the value of a given type of expression
Assuming as in your example that unsigned int
has a value range of 0 to 4,294,967,295 the value -1 is converted by adding -1 + 4,294,967,296 = 4,294,967,295. Note that this conversion happens regardless of how negative numbers are represented on the given system. It is the same for two's complment, ones' compliment, or sign-and-magnitude.
Note that this means that the representation of the converted value need not be the same as the representation of -1.
Using a 4-bit type as an example, converting the value -1 to an unsigned type results in the value 15. The representation of these numbers is as follows:
sign-and magnitude ones' complement two's complement
-1 (signed) 1001 1110 1111
15 (unsigned) 1111 1111 1111
While in the two's complement case the result of the conversion keeps the same representation, it changes in the other two cases. For one's complement the representation of -1 is the same as for 14, and for sign-and-magnitude the representation of -1 is the same as for 9.
So what other answers have described regarding two's complement is most likely how those implementations do it (i.e. reinterpreting the representation of -1 as an unsigned value), however from the perspective of C language as an abstract machine what I've described is the only correct way of performing this conversion.