Bit Shifting

The left and right shift operators are the last two bitwise operators for us to look at.

In C (and C++), << and >> are used to shift bits around inside bytes. Not just in any random fashion – these operators move all the bits either to the left or to the right, exactly as their names imply.

Left bit shift

This is the easy one. No matter what your integer type (long, short, signed, unsigned), applying this operator always moves the bits to the left and pads with zeros from the right. The bits that move off to the left are discarded – they are gone forever and you can’t get them back.

For each place that the bits are shifted, it is the equivalent of multiplying by 2.

62 << 2 = 248    //or, multiply by 4

In binary:

0011 1110 //62
(00)1111 1000 // 248 (discarded) padded

The next example shows what happens if you use an integer that is not large enough to hold the result. 120 << 2 should give you 480, but since we are using a single byte, we lose bits from the left and the result is 224:

120 << 2 = 224

In binary:

0111 1000 //120
(01)1110 0000 // 224 (discarded) padded

Right bit shift

The right shift does the opposite of the left shift. If you are applying it to an unsigned integer this is always the case and it is always the equivalent of dividing by 2 for each place shifted (and it always rounds down towards zero).

62 >> 2 = 15    // or, divide by 4

In binary:

0011 1110 //62
0000 1111(10) // 15 padded (discarded)

Right shifting signed integers

If you apply a right shift to a signed integer, then the result may vary. On some machines, under some compilers, it will pad with sign bits, i.e. 1s for a negative number and 0s for a positive number, since the leftmost bit is the sign bit for signed integers. This is also termed the ‘arithmetic shift’. On other machines, with other compilers, it will always pad with zeros. This is termed the ‘logical shift’.

GCC, which is the compiler I use, implements the arithmetic shift. You can easily write a few lines of code to test out what your own compiler does if you can’t find details in the documentation.

Note that right shifting a negative signed integer rounds towards negative infinity, not zero. -50 >> 2 will give -13, but -50 / 4 will give -12.

Two’s complement is used to represent signed integers, so the binary representation for the negative numbers below is probably not familiar. However, you can still see how the shift is applied here. (I’d like to cover two’s complement representation at some point in the future – it requires its own post to be explained effectively.)

1100 1110 // -50
1111 0011(10) // -13 padded (discarded)

What would I use bit shifting for?

We’ll take a look at some examples next week – right now I have a 3 week old baby that needs feeding!

2 thoughts on “Bit Shifting”

  1. Came across a good gotcha the other day
    uint64_t i = 1 << 32;
    Because the 1 is a 32 bit number the shift loses the 1 so we cast a zero to 64 bits. Oops
    Hope you are still having fun!

    • Hello Mr B! Nice one – I just had a play with that on my linux machine. I got a compiler warning though. Now don’t tell me you’re working on a project that isn’t -Wall’d? 😉
      Good to hear from you – all good in your world I trust? All’s well here, still loving the bits and bytes!

Comments are closed.