Binary shift operators. How can you determine the value after the operation?
Are there simple methods to determine the output of a left or right shift on a signed number? This page describes the left shift as expr1*2*expr2 and the right shift as expr1/2*expr2, however when I try something like 27 << 5 in C I get a value that's larger than 27*2*5 = 270. Also, for negative input, such as -27 << 4 or -120 >> 5, how do these operations work? Are there special cases that one needs to consider when working with shifts?
Shifting is equivalent to multiplication by a power of 2, not just twice the product of the arguments. In other words, 27 << 5 == 27 * 25. Right shift is equivalent to floored division, but it isn't defined for negative operands.
If multiplying or dividing by a fixed power of two, it is far preferable to write it out with a * or / operator. The compiler will turn this into a faster shift operation if possible, and you avoid rough edges around negative numbers, order of operations, etc.
There are plenty of resources to help you dig deeper (or indeed which should be consulted before MSDN for non-platform-specific questions), for example Wikipedia.
When you shift (to the left) by a number of binary places, it's not a multiplication by the shift. It's a multiplication by 2^shift (2 to the power of the shift).
shift multiplier 1 2 2 4 3 8 4 16
Right shifts are the same, but effectively a division.
So.. 27 << 5 is this:
27 == 00000000 00011011 27 << 5 == 00000011 01100000 == 864
And shifting right:
27 >> 1 == 00000000 00001101 == 13 27 >> 2 == 00000000 00000110 == 6 27 >> 3 == 00000000 00000011 == 3 27 >> 4 == 00000000 00000001 == 1 27 >> 5 == 00000000 00000000 == 0
When you shift negative numbers, I believe the left-most bit is generally preserved. I'm not sure though. Honestly I've only ever shifted unsigned numbers, and I personally wouldn't trust shifting signed values.
Whenever you shift, you need to be aware of truncation (ie some bits will be lost). Often it's just zero bits being truncated, but if you shift enough (or you shift to the right) you will lose 1-bits. This is down to the capacity of your integer type, and can definitely be exploited to your advantage.