Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise shift in C [duplicate]

I got some C code that confuses me:

int a = 1;
int b = 32;
printf("%d\n %d\n", a<<b, 1<<32);

The output is

1
0

The code was run on Ubuntu 16.04 (Xenial Xerus), and I compiled it using gcc -m32 a.c with GCC version 5.4.0.

I've read some posts that have explained why a<<b outputs 1, but I don't understand why 1<<32 results to 0. I mean, what is the difference between a<<b and 1<<32?

like image 570
WilLinG Avatar asked Jan 04 '23 07:01

WilLinG


2 Answers

Shifting a 32-bit int left by 32 is undefined behavior, so any value could be produced as the result. Your C compiler should warn you about it in case of 1<<32 expression.

The reason the two outputs that you see are different is that they are produced by different code paths:

  • a << b uses variables, so it is computed at runtime by the compiled code
  • 1<<32 is a constant expression, so it is computed at compile time by the compiler itself

It looks like the compiled code performs the shift by modulo 32, so shift by 32 is the same as a shift by zero. The compiler itself, however, shifts by 32, dropping the one bit off the end. The compiler is free to do this, because this behavior is undefined. Hence, the standard does not demand any particular behavior, or even a consistent behavior among parts of the same program.

like image 59
Sergey Kalinichenko Avatar answered Jan 10 '23 19:01

Sergey Kalinichenko


a<<b and 1<<32 are undefined behaviour, because your right operand is equal to the number of bits.

C11 §6.5.7 Bitwise shift operators

Paragraph 3:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.The result is undefined if the right operand is negative, or greater than or equal to the number of bits in the left expression’s type.

Paragraph 4:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

So, if the number is shifted more than the size of integer, the behaviour is undefined.

GCC generated warning:

warning: left shift count >= width of type [-Wshift-count-overflow]
     printf("%d\n%d",a<<b,1<<32);
like image 27
msc Avatar answered Jan 10 '23 21:01

msc