Bitwise Shifting — See the Bits Move
Every integer your computer works with — every colour value, every coordinate, every flag — lives as a row of bits (0s and 1s). Bitwise shift operators reach into that row and slide the bits left or right.
The Bit Row
An 8-bit integer (uint8) looks like this, with position 0 on the right and each position holding a power of two:
Each bit’s value = 2^position. Flip a bit on and its contribution adds up.
Left Shift (<<) — Slide Left, Grow Bigger
x << n shifts every bit in x left by n positions. The leftmost bits fall off, and zeros fill in on the right.
Key property: Each left shift multiplies by 2 (as long as no bits fall off the left edge).
| Expression | Binary (8 bits) | Result | Meaning |
|---|---|---|---|
3 << 1 |
00000011 → 00000110 |
6 | 3 × 2 = 6 |
3 << 2 |
00000011 → 00001100 |
12 | 3 × 4 = 12 |
5 << 3 |
00000101 → 00101000 |
40 | 5 × 8 = 40 |
128 << 1 |
10000000 → 00000000 |
0 | overflow — fell off! |
The last row shows the danger: when the 1-bit at position 7 shifts left, it’s gone forever. No carry, no error — just a silent zero.
Right Shift (>>) — Slide Right, Shrink Down
x >> n shifts every bit right by n positions. The rightmost bits fall off, and zeros fill in on the left (for unsigned integers).
Key property: Each right shift divides by 2, rounding down (integer division).
| Expression | Binary (8 bits) | Result | Meaning |
|---|---|---|---|
40 >> 1 |
00101000 → 00010100 |
20 | 40 ÷ 2 = 20 |
40 >> 2 |
00101000 → 00001010 |
10 | 40 ÷ 4 = 10 |
40 >> 3 |
00101000 → 00000101 |
5 | 40 ÷ 8 = 5 |
7 >> 1 |
00000111 → 00000011 |
3 | 7 ÷ 2 = 3 (floor, loses remainder) |
The last row shows the trade-off: the 1-bit at position 0 (value 1) falls off. Right shift discards the remainder.
Interactive Playground
Type any number 0–255, pick a shift direction and amount, and watch the bits move.
Why This Matters
| Use Case | Operation | Why |
|---|---|---|
| Colour channels | (r << 16) | (g << 8) | b |
Pack RGB into one 32-bit int |
| Flags / bitfields | `flags | = 1 « 3` |
| Power-of-2 math | x << 1 vs x * 2 |
Compiler does it anyway, but good to recognise |
| Hash tables | hash >> 16 |
Mix high bits into lower positions |
| Pixel buffers | y * stride + (x >> 5) |
Fast row indexing with word-aligned width |
Gotchas
- Signed right shift (
>>) on negative numbers is implementation-defined in C/C++ (usually arithmetic shift, preserving the sign bit). In Python, integers are arbitrary-precision so>>is arithmetic by design. - Overflow is silent.
128 << 1doesn’t throw — you just get 0 (or a larger integer in Python). - Shift by ≥ bit-width is undefined behaviour in C/C++. Python handles it gracefully (result is 0 for left, 0 for right).