Bit manipulation means directly operating on the individual bits of an integer using bitwise operators. It is used in systems programming, embedded systems, cryptography, compression, and performance-critical code where you need to pack multiple values into a single integer or toggle hardware flags.
| Operator | Symbol | Description | Example (a=5, b=3) |
|---|---|---|---|
| AND | & | 1 if both bits are 1 | 5 & 3 = 1 (0101 & 0011 = 0001) |
| OR | | | 1 if either bit is 1 | 5 | 3 = 7 (0101 | 0011 = 0111) |
| XOR | ^ | 1 if bits differ | 5 ^ 3 = 6 (0101 ^ 0011 = 0110) |
| NOT | ~ | Flips all bits | ~5 = -6 (two's complement) |
| Left Shift | << | Shift bits left (multiply by 2) | 5 << 1 = 10 |
| Right Shift | >> | Shift bits right (divide by 2) | 5 >> 1 = 2 |
#include <stdio.h>
void printBinary(unsigned int n) {
for (int i = 7; i >= 0; i--) {
printf("%d", (n >> i) & 1);
}
}
int main() {
unsigned int a = 5; // 0000 0101
unsigned int b = 3; // 0000 0011
printf("a = %u (", a); printBinary(a); printf(")\n");
printf("b = %u (", b); printBinary(b); printf(")\n\n");
printf("a & b = %u (AND)\n", a & b); // 1
printf("a | b = %u (OR)\n", a | b); // 7
printf("a ^ b = %u (XOR)\n", a ^ b); // 6
printf("~a = %d (NOT)\n", ~a); // -6 (signed)
printf("a << 1 = %u (LEFT SHIFT = a*2)\n", a << 1); // 10
printf("a >> 1 = %u (RIGHT SHIFT = a/2)\n", a >> 1); // 2
return 0;
}
/*
a = 5 (00000101)
b = 3 (00000011)
a & b = 1 (AND)
a | b = 7 (OR)
a ^ b = 6 (XOR)
~a = -6 (NOT)
a << 1 = 10 (LEFT SHIFT = a*2)
a >> 1 = 2 (RIGHT SHIFT = a/2)
*/
These patterns appear constantly in real-world C code:
#include <stdio.h>
int main() {
unsigned int n = 0b00001010; // 10 in binary
int pos = 2; // bit position (0 = rightmost)
// SET bit at position pos (force it to 1)
n = n | (1 << pos);
printf("After SET bit %d: %u\n", pos, n); // 14 (00001110)
// CLEAR bit at position pos (force it to 0)
n = n & ~(1 << pos);
printf("After CLEAR bit %d: %u\n", pos, n); // 10 (00001010)
// TOGGLE bit at position pos (flip it)
n = n ^ (1 << pos);
printf("After TOGGLE bit %d: %u\n", pos, n); // 14 (00001110)
// CHECK if bit at position pos is set
int isSet = (n >> pos) & 1;
printf("Bit %d is %s\n", pos, isSet ? "SET" : "CLEAR");
// Check if number is even or odd using bit 0
int x = 17;
printf("\n%d is %s\n", x, (x & 1) ? "odd" : "even");
// Check if power of 2: n & (n-1) == 0
int vals[] = {1, 2, 3, 4, 8, 12, 16};
for (int i = 0; i < 7; i++) {
int v = vals[i];
printf("%2d is %s power of 2\n", v,
(v > 0 && (v & (v-1)) == 0) ? "a" : "NOT a");
}
return 0;
}
Bit fields let you pack multiple small values into a single integer within a struct. This is heavily used in embedded systems to map hardware registers.
#include <stdio.h>
// Permissions struct using bit fields
// Each field uses only the specified number of bits
struct Permissions {
unsigned int read : 1; // 1 bit
unsigned int write : 1; // 1 bit
unsigned int execute : 1; // 1 bit
unsigned int admin : 1; // 1 bit
}; // Total: 4 bits packed into one int
int main() {
struct Permissions user = {1, 1, 0, 0}; // read+write, no exec, no admin
printf("Read: %d\n", user.read); // 1
printf("Write: %d\n", user.write); // 1
printf("Execute: %d\n", user.execute); // 0
printf("Admin: %d\n", user.admin); // 0
// Grant execute permission
user.execute = 1;
printf("\nAfter granting execute:\n");
printf("Execute: %d\n", user.execute); // 1
printf("\nSize of Permissions struct: %zu bytes\n",
sizeof(struct Permissions)); // 4 bytes (one int)
return 0;
}
#include <stdio.h>
int main() {
int a = 15, b = 27;
printf("Before: a=%d, b=%d\n", a, b);
// XOR swap - works because a^b^b = a and a^a^b = b
a = a ^ b; // a = 15^27
b = a ^ b; // b = (15^27)^27 = 15
a = a ^ b; // a = (15^27)^15 = 27
printf("After: a=%d, b=%d\n", a, b); // a=27, b=15
// Note: only works when a and b are different variables
// XOR swap with same variable: a ^= a -> a becomes 0!
return 0;
}
Explore 500+ free tutorials across 20+ languages and frameworks.