Bitwise Operators 101

There are six bitwise operators in C: bitwise AND, bitwise OR, bitwise XOR, left shift, right shift and one's complement. All are binary operators (they require two operands), except the one's complement, which is unary. All operators take integral types (int, char, long) as operands.

The Bitwise AND operator; &, performs AND of corresponding bits of its operands. For example, consider two byte values (unsigned char) 0xAA and 0x55

Manipulating bits using Bitwise Operators

Bitwise AND is used to clear a particular bit, without affecting the rest

Bitwise OR is used to set a particular bit, without affecting the rest

Bitwise XOR is used to toggle a particular bit

The shift operators are used along with bitwise AND, OR and XOR to manipulate bits, or to break up multiplication/division.

One's complement is also used with the other operators to manipulate bits

It is useful to define a "bit mask" or simply, "mask" for each manipulation. A mask is a certain constant value, which is used with a (binary) bitwise operator to manipulate the bits of a given variable. The generic operation is thus:

To set a bit, the bitwise OR operator is used. To toggle a bit, the bitwise XOR operator is used. The mask in both cases is a value, which has only the particular bit set, and the rest unset. For example, to set/toggle bit4.

mask = 0001 0000 (bit4 is set, rest are zeros) Now, by bitwise ORing this mask with a variable, the variable's bit4 will be set (changed to 1).

mask = 0001 0000 (bit4 is set, rest are zeros)

Note! I refer the LSB as bit0, and MSB as bit7

Now, by bitwise ORing this mask with a variable, the variable's bit4 will be set (changed to 1).

As you might have noticed, the mask to reset a bit is the one's complement of the mask used to set a bit. This means:

mask = ~( 1 << mbit );

You can define a macro to calculate the mask at compile time. However, avr-libc already has such a macro, called _BV in <avr/io.h>. It takes one argument: the position whose bit is to be manipulated (mbit in above examples). The above examples can be coded as:

variable |= _BV(4);
variable ^= _BV(4);
variable &= ~_BV(4);

Manipulating multiple bits

What if you want to set/toggle/reset bit2, bit4 and bit6? The mask in this case is simply the bitwise ORs of masks for each case. That is: