Bitwise Operations
What are bitwise operators?
Most operators in C work on whole numbers. Bitwise operators go one level deeper — they work on the individual bits (the 0s and 1s) that make up a number. This makes them perfect for compact flags, masks, and clever fast tricks.
To follow along, remember that a small number like 5 is stored as bits: 5 = 0101 and 3 = 0011. Bitwise operators compare or move these bits.
The six operators
| Operator | Name | What it does |
|---|---|---|
& | AND | 1 only if both bits are 1 |
| | OR | 1 if either bit is 1 |
^ | XOR | 1 only if the bits differ |
~ | NOT | Flips every bit |
<< | Left shift | Moves bits left (×2 each) |
>> | Right shift | Moves bits right (÷2 each) |
AND, OR, XOR by example
Let's use 5 (0101) and 3 (0011) and see each result bit by bit.
#include <stdio.h>
int main() {
int a = 5, b = 3; // 0101 and 0011
printf("a & b = %d\n", a & b); // 0001 = 1
printf("a | b = %d\n", a | b); // 0111 = 7
printf("a ^ b = %d\n", a ^ b); // 0110 = 6
return 0;
}a & b = 1
a | b = 7
a ^ b = 6
AND keeps only the bits that are 1 in both. OR keeps a 1 if either has it. XOR keeps a 1 only where they differ.
NOT and the shift operators
~ flips every bit. Shifts slide the bits left or right, which multiplies or divides by powers of two.
#include <stdio.h>
int main() {
int x = 4; // 0100
printf("x << 1 = %d\n", x << 1); // 1000 = 8 (×2)
printf("x >> 1 = %d\n", x >> 1); // 0010 = 2 (÷2)
printf("~x = %d\n", ~x); // flips all bits
return 0;
}x << 1 = 8
x >> 1 = 2
~x = -5
x << 1 equals x * 2, and x >> 1 equals x / 2. Shifting is a very fast way to multiply or divide by powers of two.
Bitwise & vs logical &&
This confuses many beginners. They look similar but do completely different jobs.
| Expression | Type | Result of 5 and 3 |
|---|---|---|
5 & 3 | Bitwise AND | 1 (compares bits) |
5 && 3 | Logical AND | 1 (both are true) |
Use & for bit operations and && for conditions. Writing if (a & b) when you meant if (a && b) can silently give wrong logic.
Useful bit tricks
These three patterns come up constantly in interviews and real code:
// check if bit at position pos is set int isSet = (x >> pos) & 1; // set (turn on) the bit at pos x = x | (1 << pos); // clear (turn off) the bit at pos x = x & ~(1 << pos);
You will also see XOR used to check if a number is odd (x & 1) and to swap without a temp variable (see swap without a third variable).
Common mistakes
- Confusing bitwise
&/|with logical&&/||. - Shifting by more bits than the type has, which is undefined behaviour.
- Expecting
~xto just remove a value — it flips every bit, often giving a negative number. - Using bitwise operators on
floatordouble— they only work on integers.
Write a program that reads a number and prints whether each of its lowest 4 bits is 0 or 1, using (x >> i) & 1 in a loop. Test it with 5, 8 and 15.
Summary
- Bitwise operators act on individual bits:
&,|,^,~,<<,>>. - AND keeps common 1s, OR combines, XOR marks differences, NOT flips.
- Left shift multiplies and right shift divides by powers of two.
- Bitwise
&is not the same as logical&&. - Check/set/clear a bit with shift-and-mask patterns.
Frequently Asked Questions
What are bitwise operators in C?
&, OR |, XOR ^, NOT ~, left shift << and right shift >>. They are used for low-level tasks like flags, masks and fast arithmetic.What is the difference between & and && in C?
& is the bitwise AND — it compares the two numbers bit by bit and produces a number. Double && is the logical AND — it treats each side as true/false and produces 1 or 0. Using one where you meant the other is a very common bug.What does the left shift operator do?
x << n moves all bits of x to the left by n positions, filling with zeros on the right. Each single left shift doubles the value, so x << 1 is like multiplying by 2 and x << 3 multiplies by 8.What is XOR used for in C?
^ gives 1 only when the two bits differ. It is used to toggle bits, to swap two numbers without a temporary variable, and in simple checksums and encryption. A handy property is that any value XOR-ed with itself becomes 0.How do I check whether a specific bit is set in C?
(x >> pos) & 1 gives 1 if that bit is set, otherwise 0. This is the standard way to read an individual bit.