Why convert 0xffffffff to decimal is -1 in C? - 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

Related

unexpected behavior of unsigned variables when assigned negative values

Here is a code snippet:
unsigned short a=-1;
unsigned char b=-1;
char c=-1;
unsigned int x=-1;
printf("%d %d %d %d",a,b,c,x);
Hhy the output is this:
65535 255 -1 -1
?
Can anybody please analyze this ?
You are printing the values using %d which is for signed numbers. The value is "converted" to a signed number (it actually stays the same bitwise, but the first bit is interpreted differently).
As for unsigned char and short - they are also converted to 32 bit int, so the values fit in it.
Had you used %lld (and cast the value as long long, otherwise it could be unspecified behavior) even the last two numbers may get printed as unsigned.
Anyway, use %u for unsigned numbers.
How does it work?
Bit value of 255 is 11111111. If treated like an unsigned number, it will be 255. If treated as a signed number - it'll be -1 (the first bit usually determines sign).
When you pass the value to %d in printf, the value is converted to a 32 bit integer, which looks like this: 00000000000000000000000011111111. Since the first bit is 0, the value is printed simply as 255. It works similarily for your short.
The situation is different for 32 bit integer. It is immediately assigned a 11111111111111111111111111111111 value, which stands for -1 in singed notation. And since you have used %d in your printf, it is interpreted as -1.
Basically, you should not assign negative values to "unsigned" variables. You are trying to play tricks on the compiler, and who knows what it will do. Now, "char n = -1;" is OK because "n" can legitimently take on negative values and the compiler knows how to treat it.

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.

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.

C Unsigned int providing a negative value?

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.

Why does printf() output -1 for large integers?

I'm reading the second edition of K&R book and one of the exercises requires printing all maximum integer values defined in limits.h header. However, this...
printf("unsigned int: 0 to %d\n", UINT_MAX);
... outputs the following:
unsigned int: 0 to -1
How come I get -1? Anyone could explain this behaviour?
I'm using Digital Mars C compiler on Vista.
This is because UINT_MAX resolves to -1 if treated as a signed integer. The reason for this is, that integers are represented in two's-complement. As a consequence, -1 and 4294967296 (i.e. UINT_MAX) have the same bit representation (0xFFFFFFFF, i.e. all bits set) and that's why you get a -1 here.
Update:
If you use "%u" as the format string you will get the expected result.
In the printf, I believe %d is a signed decimal integer, try %u instead.
The max value of an unsigned int has the most significant bit set (it is all 1s). With a signed int, the most significant bit specifies negative numbers, so when you're printing an unsigned int as a signed int, printf thinks it is negative.

Resources