C · Course navigation

C bit manipulation and flags

Set, clear, test, and toggle bits with &, |, ^, ~, and shifts, and count set bits.

On this page
Before you start

C integers and the bitwise operators.

  • Set, clear, test, and toggle bits with &, |, ^, ~, and shifts, and count set bits.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

Bitwise operators work on the individual bits of integers. A flag is one bit with a name, defined as a shifted constant such as 1u << 2. OR sets a flag, AND with the complement clears it, XOR toggles it, and AND tests it. Packing several yes/no options into one integer is common in file permissions, hardware registers, and network protocols.

x & (x - 1) clears the lowest set bit. Repeating it until the value is zero counts the set bits, and a value with exactly one set bit is a power of two. XOR can swap two integers without a temporary, though a temporary is clearer. Use unsigned types for bit work, because shifting signed values into the sign bit is undefined or implementation-defined.

Code example

C
#include <stdint.h>
#include <stdio.h>

#define FLAG_READ (1u << 0)
#define FLAG_WRITE (1u << 1)
#define FLAG_EXEC (1u << 2)

static int popcount(uint32_t x) {
  int count = 0;
  while (x != 0) {
    x &= x - 1;
    count++;
  }
  return count;
}

static int is_power_of_two(uint32_t x) {
  return x != 0 && (x & (x - 1)) == 0;
}

int main(void) {
  unsigned perms = FLAG_READ | FLAG_WRITE;
  printf("can write: %d\n", (perms & FLAG_WRITE) != 0);
  perms |= FLAG_EXEC;
  perms &= ~FLAG_WRITE;
  perms ^= FLAG_READ;
  printf("perms: %u\n", perms);
  printf("popcount(255) = %d, popcount(1024) = %d\n", popcount(255), popcount(1024));
  printf("64 is a power of two: %d, 66: %d\n", is_power_of_two(64), is_power_of_two(66));

  int a = 5, b = 9;
  a ^= b;
  b ^= a;
  a ^= b;
  printf("swapped: a=%d b=%d\n", a, b);
  return 0;
}
Output
can write: 1
perms: 4
popcount(255) = 8, popcount(1024) = 1
64 is a power of two: 1, 66: 0
swapped: a=9 b=5

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1#include <stdint.h>
2#include <stdio.h>
3
4#define FLAG_READ (1u << 0)
5#define FLAG_WRITE (1u << 1)
6#define FLAG_EXEC (1u << 2)
7
8static int popcount(uint32_t x) {
9 int count = 0;
10 while (x != 0) {
11 x &= x - 1;
12 count++;
13 }
14 return count;
15}
16
17static int is_power_of_two(uint32_t x) {
18 return x != 0 && (x & (x - 1)) == 0;
19}
20
21int main(void) {
22 unsigned perms = FLAG_READ | FLAG_WRITE;
23 printf("can write: %d\n", (perms & FLAG_WRITE) != 0);
24 perms |= FLAG_EXEC;
25 perms &= ~FLAG_WRITE;
26 perms ^= FLAG_READ;
27 printf("perms: %u\n", perms);
28 printf("popcount(255) = %d, popcount(1024) = %d\n", popcount(255), popcount(1024));
29 printf("64 is a power of two: %d, 66: %d\n", is_power_of_two(64), is_power_of_two(66));
30
31 int a = 5, b = 9;
32 a ^= b;
33 b ^= a;
34 a ^= b;
35 printf("swapped: a=%d b=%d\n", a, b);
36 return 0;
37}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
OR combines two flags: bits 0 and 1 are set, so perms is 3.perms = 0b011
—
Set the execute bit: 0b111.perms = 0b111
—
Clear the write bit: 0b101.perms = 0b101
—
Toggle the read bit off: 0b100, which is 4.perms = 0b100
—
Only the execute flag remains.perms = 0b100
can write: 1
perms: 4
Each pass removes the lowest set bit, so the number of passes is the number of set bits.perms = 0b100
can write: 1
perms: 4
255 has eight set bits and 1024 has one.perms = 0b100
can write: 1
perms: 4
popcount(255) = 8, popcount(1024) = 1
A power of two has a single bit set, so x & (x - 1) is 0.perms = 0b100
can write: 1
perms: 4
popcount(255) = 8, popcount(1024) = 1
64 is a power of two: 1, 66: 0
Three XORs exchange the values.perms = 0b100
can write: 1
perms: 4
popcount(255) = 8, popcount(1024) = 1
64 is a power of two: 1, 66: 0
swapped: a=9 b=5

Behind the scenes

How C processes this code

The C compiler produces a native program. Variables occupy memory, and execution enters main.

Cost and common mistakes

popcount takes O(k) steps for k set bits; the other operations are O(1).

  • Operator precedence trips people up: x & FLAG == 0 parses as x & (FLAG == 0). Always parenthesize.
  • Shifting by a negative amount or by the width of the type or more is undefined behaviour.
  • The XOR swap breaks if both operands are the same variable, since it zeroes it. Prefer a temporary variable.

Try it yourself

How do you test whether the execute flag is set?

Reveal answer and reasoning

(perms & FLAG_EXEC) != 0 is true when the bit is set.

Further reading