C Bitwise Operations
Computers store all data — numbers, characters, everything — as sequences of bits (0s and 1s). Bitwise operators in C let you directly manipulate individual bits inside an integer value. These operators work at the binary level, making them extremely fast and memory-efficient.
Bitwise operations are used in embedded systems, device drivers, cryptography, graphics, and anywhere performance and memory usage matter.
Binary Refresher
Before working with bitwise operators, it helps to see how numbers look in binary:
| Decimal | Binary (8-bit) |
|---|---|
| 0 | 00000000 |
| 1 | 00000001 |
| 5 | 00000101 |
| 10 | 00001010 |
| 12 | 00001100 |
| 255 | 11111111 |
Bitwise Operators in C
| Operator | Symbol | Name |
|---|---|---|
| AND | & | Bitwise AND |
| OR | | | Bitwise OR |
| XOR | ^ | Bitwise XOR (Exclusive OR) |
| NOT | ~ | Bitwise Complement (NOT) |
| Left Shift | << | Left Shift |
| Right Shift | >> | Right Shift |
1. Bitwise AND ( & )
The AND operator compares each pair of corresponding bits. The result bit is 1 only if both bits are 1. If either bit is 0, the result is 0.
Think of it like: Two switches controlling one light. The light turns on only when both switches are ON.
Truth table for AND:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
#include <stdio.h>
int main()
{
int a = 12; // binary: 00001100
int b = 10; // binary: 00001010
int result = a & b;
// 00001100 (12)
// & 00001010 (10)
// ----------
// 00001000 (8)
printf("12 & 10 = %d\n", result); // Output: 8
return 0;
}
Common Use: Check if a number is even or odd
if (num & 1) {
printf("Odd\n");
} else {
printf("Even\n");
}
// If the last bit is 1, the number is odd
2. Bitwise OR ( | )
The OR operator compares each pair of bits. The result bit is 1 if at least one of the bits is 1. Both bits must be 0 for the result to be 0.
Think of it like: Two doors to a room. You can enter if at least one door is open.
Truth table for OR:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
#include <stdio.h>
int main()
{
int a = 12; // binary: 00001100
int b = 10; // binary: 00001010
int result = a | b;
// 00001100 (12)
// | 00001010 (10)
// ----------
// 00001110 (14)
printf("12 | 10 = %d\n", result); // Output: 14
return 0;
}
Common Use: Set a specific bit to 1
int flags = 0b00000000;
flags = flags | (1 << 3); // Set bit 3 to 1
// Result: 0b00001000
3. Bitwise XOR ( ^ )
The XOR (Exclusive OR) operator gives a result of 1 only when the two bits are different. If both bits are the same (both 0 or both 1), the result is 0.
Think of it like: A toggle switch — XOR flips the state.
Truth table for XOR:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
#include <stdio.h>
int main()
{
int a = 12; // binary: 00001100
int b = 10; // binary: 00001010
int result = a ^ b;
// 00001100 (12)
// ^ 00001010 (10)
// ----------
// 00000110 (6)
printf("12 ^ 10 = %d\n", result); // Output: 6
return 0;
}
XOR Trick: Swap two numbers without a temp variable
int x = 5, y = 9;
x = x ^ y; // x = 5 ^ 9 = 12
y = x ^ y; // y = 12 ^ 9 = 5
x = x ^ y; // x = 12 ^ 5 = 9
// Now x = 9, y = 5 — swapped!
4. Bitwise NOT / Complement ( ~ )
The NOT operator flips every bit — all 0s become 1s and all 1s become 0s. This is called the one's complement.
#include <stdio.h>
int main()
{
int a = 12; // binary: 00000000 00000000 00000000 00001100
int result = ~a; // flips all bits
// ~12 = -13 (in two's complement representation)
printf("~12 = %d\n", result); // Output: -13
return 0;
}
The formula for NOT on integers: ~n = -(n + 1)
5. Left Shift ( << )
The left shift operator moves all bits to the left by a specified number of positions. Bits shifted out from the left are discarded. New 0 bits fill in from the right.
Effect: Each left shift by 1 multiplies the number by 2.
#include <stdio.h>
int main()
{
int a = 5; // binary: 00000101
int result = a << 2; // shift left by 2
// 00000101 << 2 = 00010100 = 20
printf("5 << 2 = %d\n", result); // Output: 20
// 5 * 2^2 = 5 * 4 = 20
return 0;
}
6. Right Shift ( >> )
The right shift operator moves all bits to the right by a specified number of positions. Bits shifted out from the right are discarded. For positive numbers, 0 fills from the left.
Effect: Each right shift by 1 divides the number by 2 (integer division).
#include <stdio.h>
int main()
{
int a = 20; // binary: 00010100
int result = a >> 2; // shift right by 2
// 00010100 >> 2 = 00000101 = 5
printf("20 >> 2 = %d\n", result); // Output: 5
// 20 / 2^2 = 20 / 4 = 5
return 0;
}
Shift as Multiplication and Division
| Operation | Equivalent Math | Example |
|---|---|---|
n << 1 | n × 2 | 5 << 1 = 10 |
n << 2 | n × 4 | 5 << 2 = 20 |
n << 3 | n × 8 | 5 << 3 = 40 |
n >> 1 | n ÷ 2 | 20 >> 1 = 10 |
n >> 2 | n ÷ 4 | 20 >> 2 = 5 |
Real-World Uses of Bitwise Operations
| Use Case | Operator Used | How |
|---|---|---|
| Check if odd | AND | num & 1 → 1 means odd |
| Set a bit | OR | flags |= (1 << n) |
| Clear a bit | AND + NOT | flags &= ~(1 << n) |
| Toggle a bit | XOR | flags ^= (1 << n) |
| Fast multiply by 2 | Left Shift | n << 1 |
| Fast divide by 2 | Right Shift | n >> 1 |
| Swap without temp | XOR | Three XOR operations |
Summary
Bitwise operators in C work directly on the binary representation of integers. The AND operator produces 1 only when both bits are 1. The OR operator produces 1 when at least one bit is 1. The XOR operator produces 1 when the bits differ. The NOT operator flips all bits. The left shift operator multiplies by powers of 2, and the right shift operator divides by powers of 2. These operators are powerful tools for writing efficient, low-level code — especially in embedded systems, graphics, and performance-critical applications.
