C Unsigned int providing a negative value? - c

I have an unsigned integer but when i print it out using %d there is sometimes a negative value there?

Printing %d will read the integer as a signed decimal number, regardless of its defined type.
To print unsigned numbers, use %u.
This happens because of C's way to handle variable arguments. The compiler just pulls values from the stack (typed as void* and pointing to the call stack) and printf has to figure out what the data contains from the format string you give it to.
This is why you need to supply the format string - C has no way of RTTI or a 'base class' (Object in Java, for example) to get a generic or predefined toString from.

This should work:
unsigned int a;
printf("%u\n", a);
Explanation: On most architectures, signed integers are represented in two's complement. In this system, positive numbers less than 2**(N-1) (where N = sizeof(int)) are represented the same way regardless whether you are using an int or a unsigned int. However, if the number in your unsigned int is larger than 2**(N-1), it represents a negative signed number under two's complement -- which is what printf gave you when you passed it "%d".

%d means printf will interpret the value as an int(which is signed). use %u if it is an unsigned int.

Related

Can we assign integer with negative number to unsigned integer?

#include<stdio.h>
#include<conio.h>
main()
{
int i=-5;
unsigned int j=i;
printf("%d",j);
getch();
}
O/p
-----
-5
#include<stdio.h>
#include<conio.h>
main()
{
int i=-5;
unsigned int j=i;
printf("%u",j);
getch();
}
O/p
===
4255644633
Here I am not getting any compilation error .
It is giving -5 when print with the identifier %d and when printing with %u it is printing some garbage value .
The things I want to know are
1) Why compiler ignores when assigned integer with negative number to unsigned int.
2) How it is converting signed to unsigned ?
Who are "we?"
There's no "garbage value", it's probably just the result of viewing the bits of the signed integer as an unsigned. Typically two's complement will result in very large values for many a negative values. Try printing the value in hex to see the pattern more clearly, in decimal they're often hard to decipher.
I'd simply add that the concept of signed or unsigned is something that humans appreciate more than machines.
Assuming a 32-bit machine, your value of -5 is going to be represented internally by the 32-bit value 0xFFFFFFFB (two's complement).
When you insert printf("%d",j); into your source code, the compiler couldn't care less whether j is signed or unsigned, it just shoves 0xFFFFFFFB onto the stack and then a pointer to the "%d" string. The printf function when called looks at the format string, sees the %d and knows from that that it has to interpret the 0xFFFFFFFB as a signed value, hence the reason for it displaying -5 despite j being an unsigned int.
On the other hand, when you write printf("%u",j);, the "%u" makes printf interpret your 0xFFFFFFFB as an unsigned value. That value is 2^32 - 5, or 4294967291.
It's the format string passed to printf that determines how the value will be interpreted, not the type of the variable j.
There's noting unusual in the possibility to assign a negative value to an unsigned variable. The implicit conversion that happens in such cases is perfectly well defined by C language. The value is brought into the range of the target unsigned type in accordance with the rules of modulo arithmetic. The modulo is equal to 2^N, where N is the number of value bits in the unsigned recipient. This is how it has always been in C.
Printing an unsigned int value with %d specifier makes no sense. This specifier requires a signed int argument. Because of this mismatch, the behavior of your first code is undefined.
In other words, you got it completely backwards with regards to which value is garbage and which is not.
Your first code is essentially "printing garbage value" due to undefined behavior. The fact that it happens to match your original value of -5 is just a specific manifestation of undefined behavior.
Meanwhile, the second code is supposed to print a well-defined proper value. It should be result of conversion of -5 to unsigned int type by modulo UINT_MAX + 1. In your case that modulo probably happens to be 2^32 = 4294967296, which is why you are supposed to see 4294967296 - 5 = 4294967291.
How you managed to get 4255644633 is not clear. Your 4255644633 is apparently a result of different code, not the one you posted.
You can and you should get a warning (or perhaps failure) depending on the compiler and the settings.
The value you get is due to twos-complement.
The output in the second case is not a garbage value...
int i=-5;
when converted to binary form the Most Significant Bit is assigned '1' as -5 is a negative number..
but when u use %u the binary form is treated as a normal number and the 1 in MSB is treated a part of normal number..

Difference between '(unsigned)1' and '(unsigned)~0'

What is the difference between (unsigned)~0 and (unsigned)1. Why is unsigned of ~0 is -1 and unsigned of 1 is 1? Does it have something to do with the way unsigned numbers are stored in the memory. Why does an unsigned number give a signed result. It didn't give any overflow error either. I am using GCC compiler:
#include<sdio.h>
main()
{
unsigned int x=(unsigned)~0;
unsigned int y=(unsigned)1;
printf("%d\n",x); //prints -1
printf("%d\n",y); //prints 1
}
Because %d is a signed int specifier. Use %u.
which prints 4294967295 on my machine.
As others mentioned, if you interpret the highest unsigned value as signed, you get -1, see the wikipedia entry for two's complement.
Your system uses two's complement representation of negative numbers. In this representation a binary number composed of all ones represent the biggest negative number -1.
Since inverting all bits of a zero gives you a number composed of all ones, you get -1 when you re-interpret the number as a signed number by printing it with a %d which expects a signed number, not an unsigned one.
First, in your use of printf you are telling it to print the number as signed ("%d") instead of unsigned ("%u").
Second, you are right in that it has "something to do with the way numbers are stored in memory". An int (signed or unsigned) is not a single bit on your computer, but a collection of k bits. The exact value of k depends on the specifics of your computer architecture, but most likely you have k=32.
For the sake of succinctness, lets assume your ints are 8 bits long, so k=8 (this is most certainly not the case, unless you are working on a very limited embedded system,). In that case (int)0 is actually 00000000, and (int)~0 (which negates all the bits) is 11111111.
Finally, in two's complement (which is the most common binary representation of signed numbers), 11111111 is actually -1. See http://en.wikipedia.org/wiki/Two's_complement for a description of two's complement.
If you changed your print to use "%u", then it will print a positive integer that represents (2^k-1) where k is the number of bits in an integer (so probably it will print 4294967295).
printf() only knows what type of variable you passed it by what format specifiers you used in your format string. So what's happening here is that you're printing x and y as signed integers, because you used %d in your format string. Try %u instead, and you'll get a result more in line with what you're probably expecting.

Why convert 0xffffffff to decimal is -1 in C?

I thought the result would be (2**32 - 1)
#include <stdio.h>
int main(){
unsigned int a = 0xffffffff;
printf("the size of int a %d\n",a);
return 0;
}
but it gives me -1, any idea?
You're using the wrong format string. %d is a signed decimal int. You should use %u.
printf has no knowledge of the types of variables you pass it. It's up to you to choose the right format strings.
You're asking printf() to interpret that value as a signed integer, whose range is -(2**31) to (2**31)-1. Basically, the high bit is a sign bit. Read about two's complement.
The %d format specifier is used for printing signed integers, and since you're passing in 0xffffffff, printf is correctly outputting -1.
The issue is that the %d specifier is for signed integers. You need to use %u.
printf("%d",0xffffffff); // Will print -1
printf("%u",0xffffffff); // Will print 4294967295
By the way, I would expect to see a compiler warning here -- something along the lines of "printf() expects int value but argument has unsigned long int type", because most compilers detect the type mismatch.
Because %d represents a signed integer. With a signed integer, the high bit (32nd bit) is set when the integer is negative, or not as the case may be. In 0xFFFFFFFF the high bit is set, so when casting to a signed integer, the result is negative. To treat the high bit as part of the number itself, use an unsigned type
%lu or %u

When will an unsigned int variable becomes negative

I was going through the existing code and when debugging the UTC time which is declared as
unsigned int utc_time;
I could get some positive integer every time by which I would be sure that I get the time. But suddenly in the code I got a negative value for the variable which is declared as an unsigned integer.
Please help me to understand what might be the reason.
Unsigned integers, by their very nature, can never be negative.
You may end up with a negative value if you cast it to a signed integer, or simply assign the value to a signed integer, or even incorrectly treat it as signed, such as with:
#include <stdio.h>
int main (void) {
unsigned int u = 3333333333u;
printf ("unsigned = %u, signed = %d\n", u, u);
return 0;
}
which outputs:
unsigned = 3333333333, signed = -961633963
on my 32-bit integer system.
When it's cast or treated as a signed type. You probably printed your unsigned int as an int, and the bit sequence of the unsigned would have corresponded to a negative signed value.
ie. Perhaps you did:
unsigned int utc_time;
...
printf("%d", utc_time);
Where %d is for signed integers, compared to %u which is used for unsigned. Anyway if you show us the code we'll be able to tell you for certain.
There's no notion of positive or negative in an unsigned variable.
Make sure you using
printf("%u", utc_time);
to display it
In response to the comment %u displays the varible as an unsigned int where as %i or %d will display the varible as a signed int.
Negative numbers in most (all?) C programs are represented as a two's complement of the unsigned number plus one. It's possible that your debugger or a program listing the values doesn't show it as an unsigned type so you see it's two's complement.

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?
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.
Your program has undefined behavior because you passed the wrong type to printf (you told it you were going to pass an int but you passed an unsigned int). Consider yourself lucky that the "easiest" thing for the implementation to do was just silently print the wrong value and not jump to some code that does something harmful...
What you are missing is that the printf("%d",x) expects x to be signed, so although you assign -12 to x it is interpreted as 2's complement which would be a very large number.
However when you pass this really large number to printf it interprets it as signed thus correctly translating it back to -12.
The correct syntax to print a unsigned in print f is "%u" - try this and see what it does!
The assignment of a negative value to an unsigned int does not compute the absolute value of the negative: it interprets as an unsigned int the binary representation of the negative value, i.e., 4294967284 (2^32 - 12).
printf("%d") performs the opposite interpretation. This is why your program displays -12.
int and unsigned int are used to allocate a number of bytes to store a value nothing more.
The compiler should give warnings about signed mismatching but it really does not affect the bits in the memory that represent the value -12.
%x, %d, %u etc tells the compiler how to interrupt a number of bits when you print them.
When you are trying to display the int value you are passing it to a (int) argument and not a (unsigned int) argument and that causes it to print -12 and not 4294967284. Integers are stored in hexadecimal format and -12 for int is the same as 4294967284 for unsigned int in hexadecimal format..
That is why "%u" prints the right value you want and not "%d".. It depends on your argument type..GOOD LUCK!
The -12 is in 16-bit 2's compliment format. So do this:
if (x & 0x8000) { x = ~x+1; }
This will convert the 2's compliment -ve number to the equivalent +ve number. Good luck.
When the compiler implicitly converts -12 to an unsigned integer, the underlying binary representation remains unaltered. This conversion is purely semantic. The sign bit of the two's complement integer becomes the most significant bit of the unsigned integer. Thus when printf treats the unsigned integer as a signed integer with %d, it will see -12.
In general context when only positive numbers can be stored, negative numbers are not stored explicitly but their 2's complement is stored. In the same way here, the 2's complement of -12 will be stored in 'x' and you use %u to get it.

Resources