The Code Codex
Theme
← Notes / Fundamentals

note · text14 Oct 2024 · 2 min

Bitwise operations

Every integer is stored in binary. Bitwise operations compare or move those bits one by one, without going through regular arithmetic.

Example with a = 12 (1100) and b = 10 (1010):

OperationGoJavaRuleResult
ANDa & ba & b1 if both bits are 11000 = 8
ORa | ba | b1 if at least one is 11110 = 14
XORa ^ ba ^ b1 if the bits differ0110 = 6
NOT^a~aflips every bit-13
AND NOTa &^ ba & ~bclears in a the bits set in b0100 = 4
Left shifta << 1a << 1multiplies by 211000 = 24
Right shifta >> 1a >> 1divides by 20110 = 6

Java also has >>>, which shifts right filling with zeros even for negative numbers. In Go the same effect comes from using unsigned types (uint).

Where it shows up in practice

Flags and permissions: several yes/no values stored in a single number. Unix permissions work this way: chmod 755 is 111 101 101 (owner reads, writes, executes; group and others read and execute).

const (
Read = 1 << iota // 001
Write // 010
Exec // 100
)
perm := Read | Write // turns on read and write: 011
canWrite := perm&Write != 0 // tests a bit: true
perm &^= Write // turns off write: 001
static final int READ = 1, WRITE = 1 << 1, EXEC = 1 << 2;
int perm = READ | WRITE;
boolean canWrite = (perm & WRITE) != 0;
perm &= ~WRITE;

Quick tricks: n & 1 tells whether a number is odd; n & (n - 1) == 0 tells whether it is a power of 2 (for n > 0).

Masks: extracting part of a value, like the red channel of a 0xRRGGBB color with (color >> 16) & 0xFF.

See also: Data types.