the bitwise operators (AND, OR, XOR, NOT, shifts)
Most arithmetic treats a number as a single quantity, but sometimes you want to reach inside and work on its individual bits — flip one, test another, combine two patterns bit by bit. The bitwise operators do exactly this. They line up two values bit-for-bit (or transform one value's bits) and produce a new pattern, working on each bit position independently, like running the same tiny logic gate across the whole number at once.
There are six to know, and they are simple once seen. AND (written x & y) gives a 1 in a position only where BOTH inputs are 1 — it is the 'keep only what is common' operator, and the workhorse of masking. OR (x | y) gives a 1 where EITHER input is 1 — the 'turn these on' operator. XOR, exclusive or (x ^ y), gives a 1 where the inputs DIFFER — useful for toggling and for spotting changes; XORing a value with itself gives 0. NOT (~x) flips every bit, turning 0s to 1s and back. The two SHIFTS slide the bits sideways: left shift (x << n) moves bits toward the high end, filling with zeros on the right, which multiplies an unsigned value by 2 to the n; right shift (x >> n) moves them toward the low end, roughly dividing by 2 to the n. As a concrete example, 0b1100 & 0b1010 is 0b1000, while 0b1100 | 0b1010 is 0b1110, and 0b1100 ^ 0b1010 is 0b0110.
Bitwise operators matter because they let you treat one integer as a compact bundle of independent on/off settings, and because they are extremely fast — a single CPU instruction each. They underpin masks, flags, low-level hardware control, hashing, and compression. One sharp warning that trips up beginners: do NOT confuse the bitwise operators (& and |) with the LOGICAL operators (&& and ||). The logical pair evaluate a whole expression's truthiness and short-circuit; the bitwise pair operate position-by-position on the actual bits. Writing & where you meant && (or vice versa) compiles fine and silently does the wrong thing.
0b1100 & 0b1010 = 0b1000 (AND); 0b1100 | 0b1010 = 0b1110 (OR); 0b1100 ^ 0b1010 = 0b0110 (XOR); ~0b00001111 = 0b11110000 (NOT, in 8 bits). And x << 1 doubles x; x >> 1 halves it.
Each operator works on every bit position independently.
Bitwise & and | are NOT the logical && and ||: the bitwise ones combine bits and do not short-circuit, while the logical ones evaluate truthiness and may skip the right operand — confusing them compiles cleanly but behaves wrongly.