Alex Rivera | Logout

Weird behavior of right shift operator (1 >> 32)

Asked 2010-08-03T06:59:44.183
22

I recently faced a strange behavior using the right-shift operator.

The following program:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdint.h>

int foo(int a, int b)
{
   return a >> b;
}

int bar(uint64_t a, int b)
{
   return a >> b;
}

int main(int argc, char** argv)
{
    std::cout << "foo(1, 32): " << foo(1, 32) << std::endl;
    std::cout << "bar(1, 32): " << bar(1, 32) << std::endl;
    std::cout << "1 >> 32: " << (1 >> 32) << std::endl; //warning here
    std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning here

    return EXIT_SUCCESS;
}

Outputs:

foo(1, 32): 1 // Should be 0 (but I guess I'm missing something)
bar(1, 32): 0
1 >> 32: 0
(int)1 >> (int)32: 0

What happens with the foo() function ? I understand that the only difference between what it does and the last 2 lines, is that the last two lines are evaluated at compile time. And why does it "work" if I use a 64 bits integer ?

Any lights regarding this will be greatly appreciated !


Surely related, here is what g++ gives:

> g++ -o test test.cpp
test.cpp: In function 'int main(int, char**)':
test.cpp:20:36: warning: right shift count >= width of type
test.cpp:21:56: warning: right shift count >= width of type
Edit
Report

1 Answer

3

What happens in foo is that the shift width is greater than or equal to the size of the data being shifted. In the C99 standard that results in undefined behaviour. It's probably the same in whatever C++ standard MS VC++ is built to.

The reason for this is to allow compiler designers to take advantage of any CPU hardware support for shifts. For example, the i386 architecture has an instruction to shift a 32 bit word by a number of bits, but the number of bits is defined in a field in the instruction that is 5 bits wide. Most likely, your compiler is generating the instruction by taking your bit shift amount and masking it with 0x1F to get the bit shift in the instruction. This means that shifting by 32 is the same as shifting by 0.

answered 2010-08-03T07:50:31.617

Your Answer