C bit manipulation and flags
Set, clear, test, and toggle bits with &, |, ^, ~, and shifts, and count set bits.
On this page
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
#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;
}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
#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;}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
| Step / line | What happens | State after step | Output 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.