Question

I am currently experimenting with bitwise operations in C and I am trying to understand why this code prints a different value for variable a and variable b. I know that a 32 bit shift overflows the 1 variable (that is a normal int), but my understanding is that it should print 0 in both cases.

Instead, it prints what seems like a random number with the unsigned int a and a 0 value with the unsigned long int b.

#include <stdio.h>

int main(){
  printf("%lu %lu\n",sizeof(int), sizeof(long int));
  unsigned int a = 1 << 32;
  unsigned long int b = 1 << 32;
  printf("%u %lu\n", a, b);
  return 0;
}

Sample output:

4 8
374588997 0

What am I missing?

EDIT

Now I am trying only with a 31 bit shift, the compiler gives me NO warning. Source:

#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1 << shift;
  printf("%lu\n", b);
  return 0;
}

And it outputs 18446744071562067968, that is really not 2^31. Any clue?

Was it helpful?

Solution

Change your code as below

#include <stdio.h>

int main(){
  int shift = 31;
  unsigned long int b = 1LU << shift; /* or 1U << shift */
  printf("%lu\n", b);
  return 0;
}

It seems on your system long int is 64 bit.

You are getting int result which is negative and trying to store it into 64 bit unsigned leading to the strange number.

p.s. 18446744071562067968 = FFFFFFFF80000000

OTHER TIPS

First a is random because the shift count is greater than the length of the type. This is undefined behavior:

/tmp/test.c: In function 'main':
/tmp/test.c:5:6: warning: left shift count >= width of type [enabled by default]
      unsigned int a = 1 << 32;
      ^

Now b is declared as long int, but its value is computed with 32 bit logic, since by default 1 is int:

/tmp/test.c:6:8: warning: left shift count >= width of type [enabled by default]
      unsigned long int b = 1 << 32;
      ^

The correct expression for b would be:

unsigned long int b = 1L << 32;

EDIT to answer your new question:

In C, 1 is by default signed int therefore 1 << 31 is the negative number -2147483648. Now this number gets converted to 64 bits, it becomes 0xffffffff80000000 (-2147483648 as signed long int) and finally its signedness is discarded. That's why you get 18446744071562067968 which is 0xffffffff80000000.

Your code works as expected for me (gcc 4.6.3 on 12.04LTS). But it produces couple of warnings about shift count being greater than the width of type.

Compilation gives:

Test.c: In function ‘main’:

Test.c:5:5: warning: left shift count >= width of type [enabled by default]

Test.c:6:4: warning: left shift count >= width of type [enabled by default]

Output of run:

4 8

0 0

Good Luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top