Fork me on GitHub

Project Notes

Bitwise Operations

Summary and demonstration of all the usual bit operations in C.

Notes

Manipulating individual bits of a variable or register is very common especially in embedded programming. If you studied any digital/boolean logic, the theory may be familier, but we faced with actually writing a line of bit manipulation code I often find myself mentally working it out again from first principles.

Here’s a catalog of the conventional bit operation techniques in C. Note: bitfields provide another approach for dealing with fixed size data, but I’ll cover those seperately

Building blocks

The key operators from which all these recipes can be made:

  • bitwise OR: |
  • bitwise AND: &
  • bitwise XOR: ^
  • bitwise NOT: ~ to invert (ones’ complement)
  • shift: << ,>> to shift bits left or right
  • assignment: = but often compounded with a bitwise operation e.g. |=, &=, ^=, ~=

Note: bitwise operators are not to be confused with their logical analogs: ||, &&, !.

Setting a bit

Shift a bit to the desired position to be set and OR it with the current value. e.g. to set bit position p:

value |= 1 << p;

Clearing a bit

Create a bit mask with all bits set to 1 except those to be cleared. AND this with the current value to clear all the unmasked bits e.g. to clear bit position p:

value &= ~(1 << p);

Toggle a bit

Shift a bit to the desired position to be toggled and XOR with the current value.

value ^= 1 << p;

Checking a bit

Shift a bit to the desired position to be checked and AND with the current value. The result will be non-zero of the bit is set.

value & (1 << p)

To coerce to a boolean result, compare with 0 (for example:

value & (1 << p) == 0

Setting multiple bits

Setting multiple bits poses the challenge that some bits may need to be set, some cleared, all while keeping the other bits as-is.

There are a few ways to approach this. Here’s one: mask out the bits to be set in the current value, then OR with the new bits (shifted into the correct position)

For example, to set two bits[3:2] with some some_bits value:

new_bits = 0b10;
result = (value & ~(0b11 << 2)) | (new_bits << 2);

Macros

Libraries often provide macros for bit operations, though these are non-standard and often not portable. Here are some commmon ones:

The _BV “bit value” - shortcut for creating a 1-bit mask. e.g. avr/sfr_defs.h

#define _BV(bit) (1 << (bit))

Running the Examples

See example.c for details. A makefile compiles and runs:

$ make
gcc -Wall -O0    example.c   -o example
./example

===== test_bit_set
Initial value           : 0b11110000
Result of setting bit 3 : 0b11110100

===== test_bit_clear
Initial value            : 0b10101111
Result of clearing bit 2 : 0b10101011

===== test_bit_toggle
Initial value              : 0b10101111
Result of toggling bit 2   : 0b10101011
After again toggling bit 2 : 0b10101111

===== test_bit_check
Initial value     : 0b11110000
Test if bit 2 set : 0b00000000
Test if bit 6 set : 0b00000001

===== test_bit_set_multiple
Initial value               : 0b11110000
Bits to set at position 5:2 : 0b1010
Result                      : 0b11101000

NB: bit positions mentioned are 0-based from LSB

Credits and References

About LCK#170 c
Project Source on GitHub Return to the Project Catalog

This page is a web-friendly rendering of my project notes shared in the LittleCodingKata GitHub repository.

LittleCodingKata is my collection of programming exercises, research and code toys broadly spanning things that relate to programming and software development (languages, frameworks and tools).

These range from the trivial to the complex and serious. Many are inspired by existing work and I'll note credits and references where applicable. The focus is quite scattered, as I variously work on things new and important in the moment, or go back to revisit things from the past.

This is primarily a personal collection for my own edification and learning, but anyone who stumbles by is welcome to borrow, steal or reference the work here. And if you spot errors or issues I'd really appreciate some feedback - create an issue, send me an email or even send a pull-request.