Bit Manipulation: Affecting a single bit

A bitmask is a bitstring that can be used in bitwise operations to only affect certain bits. We have already seen examples of a bitmask with the eight LEDs problem. When we wanted to turn LED #1 without affecting the other LEDs, we bitwise OR’d the LED bitstring with the bitmask 00000010. What if we wanted to toggle LED #1 without affecting the other LEDs? We would bitwise XOR the LED bitstring with that same bitmask, 00000010. This bitmask corresponds to Bit 1, which in turn corresponds to LED #1. Similarly, 00010000 is a bitmask for Bit 4, which corresponds to LED #4. In each bitmask, all the bits are 0 except for the corresponding bit. In other words, a bitmask can “mask” the other bits so that they are not affected by whatever operation you perform on the desired bit.


Now, what if you wanted to turn off LED #1? Bitwise ANDing the LED bitstring with the bitmask for LED #1 would not work; it would just turn all the other LEDs off while leaving LED #1 unaffected. Instead, we could bitwise AND it with the complement of the LED #1 bitmask. We can get the complement of the bitmask by doing a bitwise NOT operation. Thus, ~00000010 = 11111101. If we bitwise AND this with the LED bitstring, only LED #1 is turned off while the others stay the same.


So now we know how to use bitmasks to manipulate the value of each bit. What if we wanted to get the value of a specific bit? As humans, we can easily glance at a bitstring and know what the value of, say, Bit 2 is. For a computer, “looking” at a specific bit equates to reading its value. In order to read a specific bit’s value, we turn to bitmasks once again, this time using the bitwise AND operation to isolate the bit. This makes all other bits 0 while retaining the value of the bit you want. Let us say that the state of the LEDs is stored in variable a and you need to see if LED #2 is on or off, then the following expression isolates bit 2 of the LED status. If the expression becomes zero, it means LED #2 is off and if the expression become non-zero, it means LED #2 is on. Note that since we are not writing back this value to a, it does not affect a and therefore the lights are unchanged.

(a & 0b00000100)

The below table summarizes the bitwise operations with masks. Note that in all operations except when clearing a bit, the mask is used directly. However, when we need to clear a certain bit, we need to use the complement of the mask for that bit and AND it with the original bitstring.