Bitwise operators

AND, OR, XOR and shifts, and packing flags into one number.

OperatorMeaning
a & bAND: 1 only where both bits are 1
a | bOR: 1 where either bit is 1
a ^ bXOR: 1 where the bits differ
~aNOT: flip every bit
a << nShift left: multiply by 2ⁿ
a >> nShift right: divide by 2ⁿ
C
#include <stdio.h>

int main(void) {
  unsigned int a = 12, b = 10;  /* 1100 and 1010 in binary */
  printf("%u %u %u\n", a & b, a | b, a ^ b);
  printf("%u %u\n", a << 1, a >> 2);

  int n = 7;
  printf("%s\n", (n & 1) ? "odd" : "even");

  unsigned int x = 29;  /* 11101 */
  int bits = 0;
  while (x != 0) {
    x &= x - 1;  /* clears the lowest 1 bit */
    bits++;
  }
  printf("%d\n", bits);

  unsigned int v = 64;
  printf("%d\n", v != 0 && (v & (v - 1)) == 0);  /* power of two? */
  return 0;
}
Output
8 14 6
24 3
odd
4
1

These tricks come up often in placement tests: n & 1 tests for odd, x & (x - 1) clears the lowest set bit, and a power of two has exactly one bit set.

Flags in one number

C
#include <stdio.h>

enum { CAN_READ = 1 << 0, CAN_WRITE = 1 << 1, CAN_DELETE = 1 << 2 };

int main(void) {
  unsigned int role = CAN_READ | CAN_WRITE;
  printf("%d\n", (role & CAN_WRITE) != 0);
  role &= ~CAN_WRITE;
  printf("%d\n", (role & CAN_WRITE) != 0);
  role |= CAN_DELETE;
  printf("%u\n", role);
  return 0;
}
Output
1
0
5

Device firmware and permission systems pack many on/off switches into one integer like this. Use unsigned types for bit work, because shifting negative numbers is not well defined in C.

← FilesC quick reference →