Assigning negative numbers to an unsigned int?
In the C programming language, unsigned int
is used to store positive values only. However, when I run the following code:
unsigned int x = -12;
printf("%d", x);
The output is still -12. I thought it should have printed out: 12, or am I misunderstanding something?
Solution 1:
The -12
to the right of your equals sign is set up as a signed integer (probably 32 bits in size) and will have the hexadecimal value 0xFFFFFFF4
. The compiler generates code to move this signed integer into your unsigned integer x
which is also a 32 bit entity. The compiler assumes you only have a positive value to the right of the equals sign so it simply moves all 32 bits into x
. x
now has the value 0xFFFFFFF4
which is 4294967284
if interpreted as a positive number. But the printf
format of %d
says the 32 bits are to be interpreted as a signed integer so you get -12
. If you had used %u
it would have printed as 4294967284
.
In either case you don't get what you expected since C language "trusts" the writer of code to only ask for "sensible" things. This is common in C. If you wanted to assign a value to x
and were not sure whether the value on the right side of the equals was positive you could have written unsigned int x = abs(-12);
and forced the compiler to generate code to take the absolute value of a signed integer before moving it to the unsigned integer.
Solution 2:
The int is unsinged, but you've told printf
to look at it as a signed int.
Try
unsigned int x = -12; printf("%u", x);
It won't print "12", but will print the max value of an unsigned int minus 11.
Exercise to the reader is to find out why :)
Solution 3:
Passing %d to printf tells printf to treat the argument as a signed integer, regardless of what you actually pass. Use %u to print as unsigned.
Solution 4:
It all has to do with interpretation of the value.
If you assume 16 bit signed and unsigned integers, then here some examples that aren't exactly correct, but demonstrate the concept.
0000 0000 0000 1100 unsigned int, and signed int value 12
1000 0000 0000 1100 signed int value -12, and a large unsigned integer.
For signed integers, the bit on the left is the sign bit. 0 = positive 1 = negative
For unsigned integers, there is no sign bit. the left hand bit, lets you store a larger number instead.
So the reason you are not seeing what you are expecting is that.
unsigned int x = -12, takes -12 as an integer, and stores it into x. x is unsigned, so what was a sign bit, is now a piece of the value.
printf lets you tell the compiler how you want a value to be displayed.
%d means display it as if it were a signed int. %u means display it as if it were an unsigned int.
c lets you do this kind of stuff. You the programmer are in control.
Kind of like a firearm. It's a tool. You can use it correctly to deal with certain situations, or incorrectly to remove one of your toes.
one possibly useful case is the following
unsigned int allBitsOn = -1;
That particular value sets all of the bits to 1
1111 1111 1111 1111
that can be useful sometimes.
Solution 5:
printf('%d', x);
Means print a signed integer. You'll have to write this instead:
printf('%u', x);
Also, it'll still not print "12", it's going to be "4294967284".