## 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

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

(bitwise AND)

1010 1010 (0xAA)

& 0101 0101 (0x55)

___________

= 0000 0000 (0x00, result)

1010 1010 (0xAA)

& 0101 0101 (0x55)

___________

= 0000 0000 (0x00, result)

Similarly, bitwise OR; | and bitwise XOR; ^, perform the OR and XOR operations on the corresponding bits:

(bitwise OR)

1010 1010 (0xAA)

| 0101 0101 (0x55)

___________

= 1111 1111 (0xFF, result)

(bitwise XOR)

1010 1010 (0xAA)

^ 0101 1010 (0x5A)

___________

= 1111 0000 (0xF0, result)

1010 1010 (0xAA)

| 0101 0101 (0x55)

___________

= 1111 1111 (0xFF, result)

(bitwise XOR)

1010 1010 (0xAA)

^ 0101 1010 (0x5A)

___________

= 1111 0000 (0xF0, result)

Left shift; <<, and right shift; >> simply shift the bits by the specified number of times:

(left shift)

0000 0001 (0x01)

<< 3 (3 times)

___________

= 0000 1000 (0x08)

(right shift)

0000 1000 (0x08)

>> 3 (3 times)

___________

= 0000 0001 (0x01, result)

0000 0001 (0x01)

<< 3 (3 times)

___________

= 0000 1000 (0x08)

(right shift)

0000 1000 (0x08)

>> 3 (3 times)

___________

= 0000 0001 (0x01, result)

The bold zeros indicate the zeros that were appended due to the shift operation.

Note! Beware of implementation defined/undefined behavior with shift operators!

The expression E1 << E2 (left shift) is defined only if

- E1 is unsigned
- E1 is signed
*and*non-negative*and*the result fits in the signed type

else, the result is undefined (the result is unpredictable)

The expression E1 >> E2 (right shift) is defined only if

- E1 is unsigned
- E1 is signed
*and*non-negative

else, the result is implementation defined (depends on the compiler, the behavior will be usually documented)

The final operator is the one's complement operator; ~, which simply inverts the bits

(one's complement)

1010 1010 (0xAA)

~

___________

= 0101 0101 (0x55, result)

1010 1010 (0xAA)

~

___________

= 0101 0101 (0x55, result)

## 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:

variable = variable <op> mask;

variable <op>= mask; (C compound assignment)

variable <op>= mask; (C compound assignment)

where <op> stands for one of the binary bitwise operators.

Setting/Toggling a bit:

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).

Setting/Toggling a bit:

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).

variable |= mask;

1010 1010 (0xAA, the variable)

| 0001 0000 (0x10, the mask)

___________

= 1011 1010 (0xBA, result)

1010 1010 (0xAA, the variable)

| 0001 0000 (0x10, the mask)

___________

= 1011 1010 (0xBA, result)

Similarly, to toggle:

variable ^= mask;

1010 1010 (0xAA, the variable)

^ 0001 0000 (0x10, the mask)

___________

= 1011 1010 (0xBA)

1011 1010 (0xBA, the variable)

^ 0001 0000 (0x10, the mask)

___________

= 1010 1010 (0xAA, result)

1010 1010 (0xAA, the variable)

^ 0001 0000 (0x10, the mask)

___________

= 1011 1010 (0xBA)

1011 1010 (0xBA, the variable)

^ 0001 0000 (0x10, the mask)

___________

= 1010 1010 (0xAA, result)

To make things simpler, the left shift operator can be used to calculate the mask. The mask is thus:

mask = 1 << mbit;

mbit is the bit position to be manipulated. For bit4, mbit = 4.

Unsetting/Resetting a bit:

This is done using the bitwise AND operator. The mask in this case is a value with the particular bit reset, and rest set. Consider resetting bit4

Unsetting/Resetting a bit:

This is done using the bitwise AND operator. The mask in this case is a value with the particular bit reset, and rest set. Consider resetting bit4

variable &= mask;

0101 0101 (0x55, the variable)

& 1110 1111 (0xEF, the mask)

___________

= 0100 0101 (0x45, result)

0101 0101 (0x55, the variable)

& 1110 1111 (0xEF, the mask)

___________

= 0100 0101 (0x45, result)

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);

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:

mask2 = 1 << 2;

mask4 = 1 << 4;

mask6 = 1 << 6;

To set/toggle:

mask = mask2 | mask4 | mask6;

To reset:

mask = ~(mask2 | mask4 | mask6 );

mask4 = 1 << 4;

mask6 = 1 << 6;

To set/toggle:

mask = mask2 | mask4 | mask6;

To reset:

mask = ~(mask2 | mask4 | mask6 );

Using the _BV macro:

mask2 = _BV(2);

mask4 = _BV(4);

mask6 = _BV(6);

To set/toggle:

mask = mask2 | mask4 | mask4;

To reset:

mask = ~( mask2 | mask4 | mask4 );

mask4 = _BV(4);

mask6 = _BV(6);

To set/toggle:

mask = mask2 | mask4 | mask4;

To reset:

mask = ~( mask2 | mask4 | mask4 );

Of course, you can directly use the _BV macro directly like this:

To set/toggle:

mask = _BV(2) | _BV(4) | _BV(6);

To reset:

mask = ~( _BV(2) | _BV(4) | _BV(6) );

mask = _BV(2) | _BV(4) | _BV(6);

To reset:

mask = ~( _BV(2) | _BV(4) | _BV(6) );

Note! Be careful of calculating masks to reset a bit. The mask value is the one's complement of bitwise ORing of individual masks, NOT the bitwise ORing of complements of individual masks. That is:

maskA = ~(_BV(0) | _BV(2));

maskB = ~_BV(0) | ~_BV(2);

maskB = ~_BV(0) | ~_BV(2);

are not equal! It may be safer to calculate the value manually for this (be sure to document the calculation in the source code!).

This page was last updated on 2009.12.24