Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot understand shift operator behavior in C code

Tags:

c

bit-shift

Look at this sample C code (extracted a test case as an example):

main() {
  unsigned long a, b;
  int c;
  c = 32;
  a = 0xffffffff << 32;
  b = 0xffffffff << c;
  printf ("a=%x, b=%x\n", a, b);
}

Prints: a=0, b=ffffffff

I cannot understand why b is not zero, just like a. I tested this on Microsoft C and GCC.

Update: I fixed the stupid typo (should have been << c and not << b of course). But my question still stands, e.g. the result is still the same.

like image 815
haimg Avatar asked Jan 30 '12 20:01

haimg


People also ask

What does the<< operator do?

Description. This operator shifts the first operand the specified number of bits to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.

Is right shift in C arithmetic?

C, however, has only one right shift operator, >>. Many C compilers choose which right shift to perform depending on what type of integer is being shifted; often signed integers are shifted using the arithmetic shift, and unsigned integers are shifted using the logical shift.

What does left shift right shift operator does respectively?

The bitwise shift operators move the bit values of a binary object. The left operand specifies the value to be shifted. The right operand specifies the number of positions that the bits in the value are to be shifted.


2 Answers

You never initialized b to anything before you use it here:

b = 0xffffffff << b;

So it can be anything. (I think you actually meant to shift by c.)


That aside:

The main issue is that shifting by the # of bits in the datatype or more is undefined behavior.
So if the literal 0xffffffff is a 32-bit integer, then the line:

a = 0xffffffff << 32;

is not defined by the standard. (See comments.)


You should also be getting a compiler warning:

warning C4293: '<<' : shift count negative or too big, undefined behavior
like image 111
Mysticial Avatar answered Oct 06 '22 22:10

Mysticial


In C it is undefined behavior to left shift more than the width of the promoted operand.

(C99, 6.5.7p3) "If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined."

I assume in the examples below int and unsigned int types are 32-bit.

The type of an unsuffixed hexadecimal integer constant is the first in the corresponding list in which its value can be represented: int, unsigned int, long, unsigned long, long long, unsigned long long.

So here 0xFFFFFFFF is of type unsigned int and 0xFFFFFFFF << 32 is undefined behavior.

like image 30
ouah Avatar answered Oct 06 '22 22:10

ouah