It's essential to master the logical bitwise operators if you're working with the individual bits of a byte on a regular basis. In the real world, it's especially useful when interfacing with industrial hardware (hardware engineers love digital I/O), working with flags, or if you're writing an emulator, in which case it's what you'll spend a lot of time doing. So here's a quick reference.
Note that you wouldn't usually create a seperate function just to perform a logical bitwise operation, I've done it in the examples below for clarity.
To test the value of a bit, use the Logical AND operator. In the following code, the bit parameter is the bit(s) to check, and the mask parameter is the value in which to test the set bit.
private bool TestBit(ushort bit, uint mask)
{
// AND
return (mask & bit) == bit ? true : false;
}
i.e. to check if bit 4 was set in a uint called MyValue:
bool Result = TestBit(8, MyValue);
To set the value of a bit, use the Logical OR operator.
private void SetBit(ushort bit, ref uint mask)
{
// OR
mask = (mask | bit);
}
Note that this could also be reduced to the following by using the bitwise OR compound assignment operator:
private void SetBit(ushort bit, ref uint mask)
{
// OR
mask |= bit;
}
To toggle bits between zero and one, use eXclusive OR, also known as XOR. Exculsive OR looks at the two values to be XOR'd together bit by bit and asks, "Is only one of these bits set in each value?" If so, the resultant bit is set. Otherwise, it is cleared.
To clarify, consider the following:
Decimal 7 = Binary 0111
Decimal 2 = Binary 0010
Decimal 5 = Binary 0101
7 XOR 2 = 5
You should be able to see why from looking at the above binary representation. Here's how we'd do it in C#:
private void ToggleBits(uint key, ref uint value)
{
// XOR parameters together
value ^= key;
}
private void PerformOp()
{
uint Value = 7;
uint Key = 2;
ToggleBits(Key, ref Value);
}
Shifting Bits
To shift bits left and right, you can use the << (shift left) or >> (shift right) operators. As with all the other logical bitwise operators, you can also combine these with an equals sign to get a compound shift operator, e.g. <<= Shifting bits to the left has the effect of multiplying your original value by 2. Consider: Decimal 7 = Binary 00111 Shifting the bits left by 1 bit gives us 01110, which is, as expected, 7 multiplied by 2, which is 14. Shifting left again gives us 11100, which is 28, or 14 multiplied by 2. In C#:
private void ShiftLeft(ref uint value, ushort numberOfBitsToShift)
{
// Shift bits left
value <<= numberOfBitsToShift;
}
If you shift a set bit outside the range of your variable, the value is lost. For example, if I shift a whole byte set to 255 to the left, I end up with 254:
11111111 << 1 = 11111110
As shifting bits is less computationally expensive than multiplying values together, historically bit shifting is a common technique employed in assembly language when something has to run as fast as possible. Graphics rendering, for example.
Shifting right has a similar effect, but divides a number by 2. I won't post code for shifting right, I'm sure you get the idea by now. If not, you're in trouble!
I should probably also cover One's and Two's Complement. I'll do that in Part II.Labels: Code Snippets, Tutorials