2

Code:

unsigned int i = 1<<31;
printf("%d\n", i);

Why the out put is -2147483648, a negative value?


Updated question:

#include <stdio.h>

int main(int argc, char * argv[]) {
    int i = 1<<31;
    unsigned int j = 1<<31;
    printf("%u, %u\n", i, j);
    printf("%d, %d\n", i, j);

    return 0;
}

The above print:

2147483648, 2147483648
-2147483648, -2147483648

So, does this means, signed int & unsigned int have the same bit values, the difference is how you treat the 31st bit when convert it to a number value?

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
Eric
  • 22,183
  • 20
  • 145
  • 196

6 Answers6

5

%d prints the int version of the unsigned int i. Try %u for unsigned int.

printf("%u\n", i);

int main(){
    printf("%d, %u",-1,-1);
    return 0;
}

Output: -1, 4294967295

i.e The way a signed integer is stored and how it gets converted to signed from unsigned or vice-versa will help you. Follow this.

To answer your updated question, its how the system represents them i.e in a 2's complement (as in the above case where -1 =2's complement of 1 = 4294967295.

thepace
  • 2,221
  • 1
  • 13
  • 21
  • 1
    Quoted in your example: `printf("%d, %u",-1,-1);` is undefined behavior. – Gyapti Jain Dec 23 '14 at 12:49
  • I checked it in codepad. But I hope you get the essence. – thepace Dec 23 '14 at 14:37
  • @thepace I checked the link to wiki, it's great ! Now I understand the history of signed number representation by computer, and why 2'complement is widely used in now days. Thanks. – Eric Dec 25 '14 at 08:30
4

printf("%d\n", i); invokes UB. i is unsigned int and you try to print it as signed int. Writing 1 << 31 instead of 1U << 31 is undefined too.

Print it as:

printf("%u\n", i);

or

printf("%X\n", i);

About your updated question, it also invokes UB for the very same reasons (If you use '1U' instead of 1, then for the reason that an int is initialized with 1U << 31 which is out of range value. If an unsigned is initialized with out of range value, modular arithmetic come into picture and remainder is assigned. For signed the behavior is undefined.)

Understanding the behavior on your platform
On your platform, int appears to be 4 byte. When you write something like 1 << 31, it converts to bit patters 0x80000000 on your machine.

Now when you try to print this pattern as signed, it prints signed interpretation which is -231 (AKA INT_MIN) in 2s completement system. When you print this as unsigned, you get expected 231 as output.


Learnings
1. Use 1U << 31 instead of 1 << 31
2. Always use correct print specifiers in printf.
3. Pass correct argument types to variadic functions.
4. Be careful when implicit typecast (unsigned -> signed, wider type -> narrow type) takes place. If possible, avoid such castings completely.

Community
  • 1
  • 1
Gyapti Jain
  • 4,056
  • 20
  • 40
  • 1
    Hi downvoter, please leave your kind comment about what is wrong in the answer. – Gyapti Jain Dec 23 '14 at 11:55
  • " When you write something like `1 << 31`, it converts to bit patters 0x80000000 on your machine." No it is UB, the compiler may generate something completely different, because UB is UB. `1U<<32==0x80000000` when `UINT_MAX>=0x80000000`, without UB. – 12431234123412341234123 Sep 14 '20 at 17:46
4

Use '%u' for unsigned int

 printf("%u\n", i);

.......................................................

Response to updated question: any sequence of bits can be interpreted as a signed or unsigned value.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
3

Try

printf("%u\n", i);

By using %d specifier, printf expects argument as int and it typecast to int. So, use %u for unsigned int.

doptimusprime
  • 9,115
  • 6
  • 52
  • 90
3

You are not doing the shift operation on an unsigned but on a signed int.

  • 1 is signed.
  • the shift operation then shifts into the sign bit of that signed (assuming that int is 32 bit wide), that is already undefined behavior
  • then you assign whatever the compiler thinks he wants for that value to an unsigned.
  • then you print an unsigned as a signed, again no defined behavior.
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
2

%u is for unsigned int.
%d is for signed int.

in your programs output :

2147483648, 2147483648     (output for unsigned int)
-2147483648, -2147483648   (output for signed int ) 
Gyapti Jain
  • 4,056
  • 20
  • 40
rabi shaw
  • 441
  • 1
  • 3
  • 14