Last 30 Days
No notifications
Every int is just a row of 0s and 1s. Bitwise operators let you read, set, clear, and toggle individual bits — used in flags, permissions, low-level protocols, graphics, embedded systems, and clever algorithm tricks.
unsigned int a = 0b1100; /* 12 */
unsigned int b = 0b1010; /* 10 */a & b /* AND -> 0b1000 = 8 */
a | b /* OR -> 0b1110 = 14 */
a ^ b /* XOR -> 0b0110 = 6 */
~a /* NOT -> flip every bit */
a << 2 /* SHIFT LEFT -> 0b110000 = 48 */
a >> 1 /* SHIFT RIGHT -> 0b0110 = 6 */
| Op | Name | What it does | |||
& | AND | bit is 1 only if BOTH bits are 1 | |||
\ | OR | bit is 1 if EITHER bit is 1 | |||
^ | XOR | bit is 1 if bits DIFFER | |||
~ | NOT | flip every bit | |||
<< | shift left | multiply by 2 per shift | |||
>> | shift right | divide by 2 per shift | The 4 Bit-Tricks You'll Memorise | Goal | Code |
Set bit n | x \ | = (1 << n) | |||
Clear bit n | x &= ~(1 << n) | ||||
Toggle bit n | x ^= (1 << n) | ||||
Test bit n | (x >> n) & 1 |
Bits are the atoms of computing. Once you understand bitwise operators you stop fearing flag enums, hardware registers, file permissions, and a whole class of clever algorithm tricks.
> Always use unsigned types for bit manipulation. Signed shifts and ~ on signed types can have implementation-defined or undefined behaviour. unsigned int (or uint32_t from ) is your friend.
A 1-byte (uint8_t) value 13:
bit index: 7 6 5 4 3 2 1 0
value: 0 0 0 0 1 1 0 1 = 8 + 4 + 1 = 13Bit 0 is the LSB (least significant bit). Bit 7 is the MSB.
1 1 0 1
& 0 1 1 1
---------
0 1 0 1Use AND to keep only the bits you want:
uint8_t low4 = x & 0x0F; /* keep bottom 4 bits, zero the rest */Test if a specific bit is on:
if (flags & FLAG_ADMIN) { ... } /* non-zero if FLAG_ADMIN bit is set */1 1 0 0
| 0 0 1 1
---------
1 1 1 1Use OR to turn bits on:
flags = FLAG_READABLE
FLAG_WRITABLE; /* enable both flags */1 1 0 0
^ 1 0 1 0
---------
0 1 1 0XOR flips a bit when the mask bit is 1:
x ^= (1 << 3); /* toggle bit 3 */XOR with itself = 0. XOR with 0 = unchanged. This gives the famous "swap without temp":
a ^= b;
b ^= a;
a ^= b; /* now a and b are swapped */(Cute, but use a temporary variable in real code — it's faster and clearer.)
uint8_t x = 0b00001111;
uint8_t y = ~x; /* 0b11110000 */Often combined with AND to clear bits:
flags &= ~FLAG_ADMIN; /* turn off the admin flag */1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
1 << 10 == 1024Each left shift doubles the value (bits move toward the MSB; zeros fill the right).
16 >> 1 == 8
16 >> 2 == 4
16 >> 4 == 1For unsigned types, zero fills from the left. For signed negatives the behaviour is implementation-defined — yet another reason to use unsigned.
| Goal | Code | Why | |
| Set bit n | x \ | = (1u << n) | OR with a 1 at position n |
| Clear bit n | x &= ~(1u << n) | AND with everything except bit n | |
| Toggle bit n | x ^= (1u << n) | XOR flips that bit | |
| Test bit n | (x >> n) & 1 | Move bit n to position 0, mask | |
| Lowest set bit | x & -x | Classic isolating trick | |
| Clear lowest set bit | x & (x - 1) | Used by popcount | |
| Power of 2? | x && !(x & (x - 1)) | Power of 2 has exactly one bit set | |
| Even? | (x & 1) == 0 | LSB tells parity | |
| Multiply by 2 | x << 1 | Faster than * 2 historically | |
| Divide unsigned by 2 | x >> 1 | Faster than / 2 historically |
This is THE most common real-world use:
enum {
PERM_READ = 1 << 0, /* 0001 = 1 */
PERM_WRITE = 1 << 1, /* 0010 = 2 */
PERM_EXECUTE = 1 << 2, /* 0100 = 4 */
PERM_DELETE = 1 << 3, /* 1000 = 8 */
};unsigned perms = 0;
perms
= PERM_READ
PERM_WRITE; /* grant read + write */
if (perms & PERM_WRITE) { ... } /* check */
perms &= ~PERM_WRITE; /* revoke write */
perms ^= PERM_EXECUTE; /* toggle execute */This is exactly how Unix file permissions, OpenGL flags, socket options, and a million APIs work.
unsigned popcount(unsigned x) {
unsigned count = 0;
while (x) {
x &= x - 1; /* clears the lowest set bit */
count++;
}
return count;
}Each iteration removes exactly one set bit, so the loop runs k times for k set bits.
Bits and hex line up nicely (each hex digit = 4 bits):
| Hex | Binary | ||||
| 0xF | 1111 | ||||
| 0xA | 1010 | ||||
| 0xFF | 11111111 | ||||
| 0xFF00 | 11111111 00000000 | So Bitwise Cheat-Sheet | Operator | Meaning | Example |
& | AND | flags & FLAG to test | |||
\ | OR | flags \ | = FLAG to set | ||
^ | XOR | flags ^= FLAG to toggle | |||
~ | NOT | ~mask to invert | |||
<< | shift left | 1 << n builds a bitmask | |||
>> | shift right | (x >> n) & 1 extracts a bit |
Bitwise operators feel like cheat codes once you internalise them — and you'll see them everywhere from competitive programming to embedded firmware.