Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning negative numbers to an unsigned int?

Tags:

c

People also ask

Can you have a negative unsigned int?

An int is signed by default, meaning it can represent both positive and negative values. An unsigned is an integer that can never be negative.

What happens when you cast a negative number to an unsigned int?

An unsigned integer will never be a negative value, the smallest value it can be is 0 (zero). The values you get are not garbage. Assigning -1 to an unsigned type will give you the maximum value that variable can hold.

How is the negative value converted to the unsigned data types?

The representation in 2s complement is not mandated by the standard but the algorithm to convert to unsigned is: "the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the newtype until the value is in the range of the newtype."

Is unsigned integer always positive?

Unsigned Integers (often called "uints") are just like integers (whole numbers) but have the property that they don't have a + or - sign associated with them. Thus they are always non-negative (zero or positive).


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.


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 :)


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.


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.


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".


They do store positive values. But you're outputting the (very high) positive value as a signed integer, so it gets re-interpreted again (in an implementation-defined fashion, I might add).

Use the format flag "%u instead.