Shifts ahoy !

Bit shifting can be troublesome. Especially if you’re not sure WHY they can be troublesome.

So some recommend only using UNSIGNED integers for such operations. And using *2 and \2 to do bit shifting.

At a very low level most modern CPUs implement certain numerical standards in various instructions. And, of note, nearly every last one has two (or more) forms of shifts. One is a logical shift, and one is an arithmetic shift.

The difference between them is VERY subtle – but important.

It turns out that this is the reason that you SHOULD use unsigned integers IF you use * 2 and \ 2 to do bit shifting. When you multiply by 2 a modern compiler might realize this is a simple arithmetic shift and write the machine code to perform exactly that operation. An arithmetic shift will preserve the sign. And so when you do a \2 operation you do not get a result that flips signs. The sign bit (left most bit) is preserved. For instance

Dim i as int8 = -8 // this is &b11111000 in binary 
                   // MSB is 1 indicating a negative value

dim j as int8 = i \ 2 
// j is now -4 which is &b11111100 in binary
// note the MSB is STILL set so the result did NOT change sign

Arithmetic shifts generally preserve the sign esp when the sign bit is initially set. Otherwise you get odd sign changes.

But the same is not true when you do a LOGICAL shift. This just moves bits without regard to signs. Starting with almost the same code, but using BITWISE.ShiftRight instead of \2 we get very different results IF you expect to get a value you can use as a number.

Dim i As Int8 = -8 // this is &b11111000 in binary 

Dim j As Int8 = BitWise.ShiftRight(i,1,8)
// j is now 124 which is &b01111100 in binary

The shift this time made NO effort to preserve the sign bit as we were doing logical shifts which make no effort to preserve the sign bit.

So when, or if, you need to do any bit manipulation make sure you understand whats going on at a low level and IF you use * and \ to do shifting use unsigned values.

Shifts away !