Arithmetic bit-shift on a signed integer

newprint picture newprint · Oct 24, 2010 · Viewed 85.3k times · Source

I am trying to figure out how exactly arithmetic bit-shift operators work in C, and how it will affect signed 32-bit integers.

To make things simple, let's say we work within one byte (8 bits):

x = 1101.0101
MSB[ 1101.0101 ]LSB

Reading other posts on Stack Overflow and some websites, I found that: << will shift toward MSB (to the left, in my case), and fill "empty" LSB bits with 0s.

And >> will shift toward LSB (to the right, in my case) and fill "empty" bits with MS bit

So, x = x << 7 will result in moving LSB to MSB, and setting everything to 0s.

1000.0000

Now, let's say I would >> 7, last result. This would result in [0000.0010]? Am I right?

Am I right about my assumptions about shift operators?

I just tested on my machine, **

int x = 1;   //000000000......01

x = x << 31; //100000000......00

x = x >> 31; //111111111......11 (Everything is filled with 1s !!!!!) 

Why?

Answer

Matthew Slattery picture Matthew Slattery · Oct 24, 2010

Right shift of a negative signed number has implementation-defined behaviour.

If your 8 bits are meant to represent a signed 8 bit value (as you're talking about a "signed 32 bit integer" before switching to 8 bit examples) then you have a negative number. Shifting it right may fill "empty" bits with the original MSB (i.e. perform sign extension) or it may shift in zeroes, depending on platform and/or compiler.

(Implementation-defined behaviour means that the compiler will do something sensible, but in a platform-dependent manner; the compiler documentation is supposed to tell you what.)


A left shift, if the number either starts out negative, or the shift operation would shift a 1 either to or beyond the sign bit, has undefined behaviour (as do most operations on signed values which cause an overflow).

(Undefined behaviour means that anything at all could happen.)


The same operations on unsigned values are well-defined in both cases: the "empty" bits will be filled with 0.