Bitwise operations, explained

Bitwise operators treat a number as a row of individual bits and combine them column by column. Four operations — AND, OR, XOR and shifts — cover almost everything you do with flags, masks and registers.

AND: keep only shared bits

A result bit is 1 only when both inputs are 1. The classic use is masking — extracting part of a value:

0110 1101 (0x6D)

& 0000 1111 (0x0F, the mask)

= 0000 1101 (0x0D — the low nibble)

x & 0xFF gives you the low byte; x & 1 tells you whether x is odd.

OR: set bits

A result bit is 1 when either input is 1. Use it to switch flags on without touching the rest:

0100 0001 (current flags)

| 0000 1000 (flag to enable)

= 0100 1001

XOR: toggle bits

A result bit is 1 when the inputs differ. XOR with a mask flips exactly those bits; XOR-ing a value with itself gives 0:

0100 1001

^ 0000 1000 (toggle that flag)

= 0100 0001

XOR's "difference detector" nature also makes it the core of checksums and parity.

Shifts: multiply and divide by two

x << n moves every bit n places left, filling with zeros — arithmetically it multiplies by 2ⁿ (until bits fall off the top). x >> n moves right, dividing by 2ⁿ.

0000 0101 (5) << 2 = 0001 0100 (20)

0001 0100 (20) >> 2 = 0000 0101 (5)

The subtlety is right-shifting negative numbers: an arithmetic shift copies the sign bit in from the left (so −8 >> 1 = −4), while a logical shift fills with zeros and produces a huge positive number. Signed types shift arithmetically, unsigned types logically — which is exactly how the signed/unsigned switch behaves in the hex calculator and in the HexCalculator app.

Why hex is the natural notation

Masks are unreadable in decimal: "240" says nothing, 0xF0 says "the high nibble" at a glance, and 1111 0000 in binary is exact but long. Since each hex digit is exactly four bits, hex is the compromise everyone uses — see the hex to binary converter to build that intuition.

Quick reference

aba AND ba OR ba XOR b
00000
01011
10011
11110

Keep exploring