Binary¶
26 cards — 🟢 5 easy | 🟡 12 medium | 🔴 3 hard
🟢 Easy (5)¶
1. What determines the meaning of a byte sequence?
Show answer
Context and interpretation. The same bits can represent an integer, text character, float component, machine instruction, or color value depending on how they are read.Example: the byte 0x41 is 'A' in ASCII, 65 as unsigned int, or part of a float — context decides.
Remember: 'Same bits, different glasses.' The interpretation layer (text codec, int type, instruction set) gives bytes meaning.
Fun fact: this is why file format headers (magic bytes) exist — they tell programs how to interpret the rest of the bytes.
2. What is the range of an unsigned 8-bit integer?
Show answer
0 to 255 (2^8 - 1).Remember: 2^8 = 256 values. Unsigned range: 0 to 255. Think 'an unsigned byte can count from zero to FF.'
Example: RGB color channels are unsigned 8-bit: each of R, G, B ranges 0-255, giving 16.7 million colors total (256^3).
Fun fact: 255 = 0xFF = 11111111 in binary. All bits set = maximum value for any unsigned integer width.
3. What is the range of a signed 8-bit integer using two's complement?
Show answer
-128 to 127. In two's complement, the most significant bit represents -(2^7) = -128, and the remaining 7 bits represent values up to 127 (0111 1111). This gives 256 distinct values: -128 through 0 through 127.Remember: signed range = -2^(n-1) to 2^(n-1)-1. For 8 bits: -128 to 127. The top bit 'costs' you half the positive range.
Gotcha: -128 has no positive counterpart in 8-bit two's complement. abs(-128) overflows back to -128!
4. Why is hexadecimal useful for representing binary data?
Show answer
Each hex digit maps to exactly 4 bits, so byte values align neatly (one byte = two hex digits). This makes hex dumps much more readable than decimal or raw binary.Remember: 1 hex digit = 4 bits = 1 nibble. 2 hex digits = 1 byte. So 0xFF = 1111 1111 = 255.
Example: MAC addresses (aa:bb:cc:dd:ee:ff), IPv6, memory addresses, and color codes (#FF0000) all use hex.
5. What decimal value does 0xff represent?
Show answer
255 (15*16 + 15, or all 8 bits set to 1).Remember: F in hex = 15 = 1111 in binary. 0xFF = 15*16 + 15 = 255 = all 8 bits set.
Example: 0xFF is used as a bitmask to extract the lowest byte: value & 0xFF gives the last 8 bits.
Fun fact: 0xDEADBEEF, 0xCAFEBABE (Java class files), and 0xFEEDFACE (Mach-O binaries) are famous hex magic numbers.
🟡 Medium (12)¶
1. What is two's complement and why is it used?
Show answer
A representation for signed integers where negative numbers are encoded so that addition works correctly at the hardware level without special cases. The CPU uses the same circuitry for both signed and unsigned addition.Remember: to negate in two's complement: flip all bits, add 1. Example: 5 = 00000101, flip = 11111010, +1 = 11111011 = -5.
Under the hood: the CPU's adder circuit works identically for signed and unsigned — that's why two's complement won.
2. What happens when a fixed-width unsigned integer overflows?
Show answer
It wraps around. For example, an 8-bit unsigned integer at 255 wraps to 0 when incremented. The behavior varies by language — some wrap silently, others trap or raise an error.Remember: 'Overflow = odometer rollover.' 255 + 1 = 0 for unsigned 8-bit, just like 999999 + 1 = 000000 on a car odometer.
Gotcha: in C, unsigned overflow is defined (wraps). Signed overflow is undefined behavior — the compiler can do anything.
3. What is endianness and why does byte order matter?
Show answer
The byte order used to store multi-byte values in memory.Little endian: least significant byte first.
Big endian: most significant byte first.
Network byte order is big endian.
Remember: 'Big-endian = big end first' (MSB at lowest address). Network byte order is always big-endian (RFC 791).
Fun fact: the terms come from Gulliver's Travels — the Lilliputians fought over which end of an egg to crack first.
Example: 0x12345678 in big-endian memory: [12][34][56][78]. Little-endian: [78][56][34][12].
4. Why does 0.1 + 0.2 produce unexpected results in many languages?
Show answer
Because 0.1 and 0.2 cannot be represented exactly in binary floating point. The stored approximations accumulate small rounding errors.Example: in Python, 0.1 + 0.2 == 0.30000000000000004. Use decimal.Decimal('0.1') + decimal.Decimal('0.2') for exact results.
Remember: 'If it's money, don't use float.' Use integer cents or a Decimal type.
5. What are the three components of an IEEE floating point number?
Show answer
Sign bit, exponent, and significand (mantissa). Together they represent the value as sign * significand * 2^exponent.Remember: 'SEM — Sign, Exponent, Mantissa.' float32: 1 sign + 8 exponent + 23 mantissa = 32 bits. float64: 1+11+52 = 64 bits.
Example: the number -6.5 = -1 * 1.625 * 2^2. Sign=1, exponent=2+127=129, mantissa=.625 encoded as 101 followed by zeros.
6. What is NaN and what is unusual about comparing it?
Show answer
NaN (Not a Number) is a special float value produced by invalid operations like 0/0. It is unique in that NaN != NaN evaluates to true — it is not equal to itself.Remember: NaN != NaN is the only value in IEEE 754 that is not equal to itself. Use math.isnan() or x != x to detect it.
Gotcha: NaN propagates — any arithmetic with NaN produces NaN. One bad sensor reading can corrupt an entire pipeline.
7. What is the safe way to compare floating point values?
Show answer
Compare within a tolerance (epsilon), not with exact equality, unless you can guarantee exact representation. For example: abs(a - b) < epsilon.Example: abs(a - b) < 1e-9 for double precision. The epsilon should scale with the magnitude of the values being compared.
Gotcha: a fixed epsilon breaks for very large or very small numbers. Use relative epsilon: abs(a-b) / max(abs(a), abs(b)) < epsilon.
8. What are the core bitwise operators and a common use case?
Show answer
AND, OR, XOR, NOT, and bit shifts. Common uses include bitmask flags, permissions (like Unix file modes), compact state storage, and parsing protocol fields.Remember: AND=mask, OR=set, XOR=toggle, NOT=invert, SHIFT=multiply/divide by powers of 2.
Example: Unix permissions use bitmasks — chmod 755 = rwxr-xr-x = 111 101 101 in binary.
9. What is byte order (endianness) and why does it matter in network programming?
Show answer
Endianness is the order bytes are stored in memory. Big-endian (MSB first) is network byte order. Little-endian (LSB first) is common on x86. Mismatched endianness corrupts multi-byte values across systems.Remember: 'Big-endian = big end first' (MSB at lowest address). Network byte order is always big-endian (RFC 791).
Fun fact: the terms come from Gulliver's Travels — the Lilliputians fought over which end of an egg to crack first.
10. Why is hexadecimal commonly used to represent binary data?
Show answer
Each hex digit represents exactly 4 bits (one nibble), so 1 byte = 2 hex digits. This is more compact than binary (8 digits) and groups cleanly on byte boundaries, unlike octal.Remember: 1 hex digit = 4 bits = 1 nibble. 2 hex digits = 1 byte. So 0xFF = 1111 1111 = 255.
Example: MAC addresses (aa:bb:cc:dd:ee:ff), IPv6, memory addresses, and color codes (#FF0000) all use hex.
11. What do the bitwise AND, OR, and XOR operators do, and name one use case for each?
Show answer
AND (&): mask bits (extract specific bits). OR (|): set bits (enable flags). XOR (^): toggle bits (simple encryption, swap without temp variable). All operate bit-by-bit on integer operands.Remember: AND(&)=mask/extract, OR(|)=set/enable, XOR(^)=toggle/flip. Mnemonic: 'AOX = And filters Out, Or adds, Xor toggles.'
Example: checking if bit 3 is set: (flags & 0x08) != 0. Setting bit 3: flags |= 0x08. Toggling: flags ^= 0x08.
12. What is memory alignment and why do compilers add padding to structs?
Show answer
Memory alignment means placing data at addresses divisible by its size (e.g., 4-byte int at 4-byte boundary). CPUs access aligned data faster. Compilers pad structs to maintain alignment, which can increase struct size.Example: struct { char a; int b; } is 8 bytes, not 5 — the compiler adds 3 padding bytes after 'a' to align 'b' on a 4-byte boundary.
Gotcha: reordering struct fields from largest to smallest minimizes padding. Tools like pahole show struct layouts.
🔴 Hard (3)¶
1. Why are floating point numbers denser near zero?
Show answer
Because the exponent scales the gap between representable values. Small exponents produce small gaps; large exponents produce large gaps. Precision is not uniform across the range.Remember: 'Small exponent = small gaps, large exponent = large gaps.' Half of all float values lie between -1 and 1.
Gotcha: between 2^23 and 2^24 (for float32), consecutive floats differ by 1.0 — you cannot represent 8388609.5.
2. Why should you avoid using floating point for monetary calculations?
Show answer
Floats cannot exactly represent many decimal fractions (like 0.10), leading to rounding errors that accumulate. Use fixed-point decimal types or integer cents instead.Example: $0.10 * 3 in float might give $0.30000000000000004. Store as integer cents: 10 * 3 = 30 cents. Display at the end.
Remember: 'Cents not floats.' Python: decimal.Decimal, Java: BigDecimal, PostgreSQL: NUMERIC. Never IEEE 754 for money.
3. How does two's complement represent negative integers, and what is -1 in 8-bit two's complement?
Show answer
Two's complement inverts all bits and adds 1. For -1: start with 00000001, invert to 11111110, add 1 = 11111111 (0xFF). This scheme allows addition of positive and negative numbers using the same hardware.Remember: 'Flip and add one' — that's the two's complement recipe. -1 is always all-ones (0xFF for 8-bit, 0xFFFFFFFF for 32-bit).
Gotcha: -1 in any width two's complement is all 1-bits. This is why bitwise NOT of 0 equals -1 in signed integers.