Computer Basics
Data Representation
How computers store everything as bits: unsigned and signed integers, two's complement, overflow, floating point, characters with ASCII and Unicode, and images and sound.
Inside a computer, everything — numbers, text, images, music, your code — is a pattern of bits. The meaning depends on how the program interprets those bits.
Unsigned integers
With n bits you can store 2ⁿ patterns: unsigned values 0 to 2ⁿ − 1.
| Bits | Unsigned range |
|---|---|
| 8 | 0 to 255 |
| 16 | 0 to 65,535 |
| 32 | 0 to about 4.29 billion |
| 64 | 0 to about 1.8 × 10¹⁹ |
Signed integers: two's complement
To store negative numbers, computers use two's complement. The leftmost bit has a negative place value: in 8 bits it is worth −128.
To find the 8-bit pattern for −x: write x in binary, invert all the bits, then add 1.
5 = 0000 0101 → invert → 1111 1010 → add 1 → 1111 1011 = −5
Check: −128 + 64 + 32 + 16 + 8 + 2 + 1 = −5 ✓.
8-bit two's complement ranges from −128 to +127; in general, −2ⁿ⁻¹ to 2ⁿ⁻¹ − 1. Two's complement is used because addition works the same way for positive and negative numbers — the CPU needs only one adder circuit.
#include <stdio.h>
void bits8(signed char x) {
for (int i = 7; i >= 0; i--) putchar((x >> i) & 1 ? '1' : '0');
}
int main(void) {
signed char values[] = {5, -5, 127, -128, -1};
for (int i = 0; i < 5; i++) {
printf("%5d = ", values[i]);
bits8(values[i]);
printf("\n");
}
return 0;
}5 = 00000101 -5 = 11111011 127 = 01111111 -128 = 10000000 -1 = 11111111
Overflow
When a result does not fit in the available bits, it wraps around:
#include <stdio.h>
#include <limits.h>
int main(void) {
unsigned char u = 255;
u = u + 1; // 256 does not fit in 8 bits
printf("255 + 1 in an unsigned char = %d\n", u);
printf("INT_MAX = %d\n", INT_MAX);
long long big = (long long)INT_MAX + 1;
printf("INT_MAX + 1 as a long long = %lld\n", big);
printf("(int)(INT_MAX + 1LL) = %d\n", (int)(INT_MAX + 1LL)); // wraps to INT_MIN
return 0;
}255 + 1 in an unsigned char = 0 INT_MAX = 2147483647 INT_MAX + 1 as a long long = 2147483648 (int)(INT_MAX + 1LL) = -2147483648
The 2038 problem is an overflow waiting to happen: many systems store time as seconds since 1 January 1970 in a signed 32-bit integer, which runs out on 19 January 2038.
Floating point
Real numbers use IEEE 754 floating point — a binary version of scientific notation:
value = (−1)^sign × 1.mantissa × 2^(exponent − bias)
| Type | Bits | Sign | Exponent | Mantissa | Precision |
|---|---|---|---|---|---|
float |
32 | 1 | 8 | 23 | about 7 decimal digits |
double |
64 | 1 | 11 | 52 | about 15–16 decimal digits |
Most decimal fractions cannot be stored exactly, so small errors creep in:
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(abs((0.1 + 0.2) - 0.3) < 1e-9) # compare with a tolerance instead
print(f"{0.1:.20f}") # what is really stored
print(1e308 * 10, -1e308 * 10) # overflow to infinity
total = 0.0
for _ in range(10):
total += 0.1 # tiny errors accumulate
print(total, total == 1.0)0.30000000000000004 False True 0.10000000000000000555 inf -inf 0.9999999999999999 False
Characters
Text is stored as numbers too.
- ASCII (1963) uses 7 bits for 128 characters: 'A' = 65, 'a' = 97, '0' = 48, space = 32, newline = 10.
- Unicode assigns a code point to every character in every script — over 150,000 of them, including Devanagari, Tamil, emoji and ₹ (U+20B9).
- UTF-8 encodes Unicode in 1 to 4 bytes, and is identical to ASCII for the first 128 characters. It is the encoding of the web.
for ch in ["A", "a", "0", "₹", "अ", "😀"]:
data = ch.encode("utf-8")
print(f"{ch!r}: code point U+{ord(ch):04X} ({ord(ch)}), UTF-8 bytes = {data.hex(' ')} ({len(data)} byte{'s' if len(data) > 1 else ''})")'A': code point U+0041 (65), UTF-8 bytes = 41 (1 byte) 'a': code point U+0061 (97), UTF-8 bytes = 61 (1 byte) '0': code point U+0030 (48), UTF-8 bytes = 30 (1 byte) '₹': code point U+20B9 (8377), UTF-8 bytes = e2 82 b9 (3 bytes) 'अ': code point U+0905 (2309), UTF-8 bytes = e0 a4 85 (3 bytes) '😀': code point U+1F600 (128512), UTF-8 bytes = f0 9f 98 80 (4 bytes)
Images and sound
- An image is a grid of pixels; each pixel stores a colour, often as 3 bytes for red, green and blue (24-bit colour). A 1920 × 1080 photo has about 2 million pixels × 3 bytes ≈ 6 MB uncompressed — which is why JPEG and PNG compression matter.
- Sound is sampled thousands of times per second: CD audio stores 44,100 samples per second, 16 bits each, per channel.
Test yourself
4 questions · pick an answer to check it instantly
- 1
What is the 8-bit two's complement representation of −1?
1 = 0000 0001; invert to 1111 1110; add 1 → 1111 1111. - 2
What is the range of an 8-bit two's complement integer?
−2⁷ to 2⁷ − 1. - 3
Why does
0.1 + 0.2 == 0.3evaluate to false?Each value is the nearest representable binary fraction, and the tiny errors do not cancel. - 4
How many bytes does UTF-8 use for an ASCII character like 'A'?
UTF-8 is backward-compatible with ASCII for the first 128 characters.