A number is one value, but several bytes
Through this rung you have treated an integer or a floating-point value as a single thing — a row of bits with one meaning. But memory is not addressed by the bit; it is addressed by the byte, a group of 8 bits, and most values are wider than one byte. A 32-bit integer is four bytes; a 64-bit value is eight. So the moment you store a multi-byte number, a new question appears that the math never raised: which byte goes at the lowest address?
Take the 32-bit value 0x1A2B3C4D. It has a most significant byte (0x1A, the big end of the number) and a least significant byte (0x4D, the small end). The four bytes must be laid out across four consecutive addresses, and there are two sensible ways to do it. This ordering choice is called endianness, and although it sounds like a footnote, it is exactly the kind of detail that silently corrupts data when one machine writes a file and another reads it back wrongly.
Big-endian and little-endian: which end comes first
Big-endian puts the big end first: the most significant byte goes at the lowest address, just like we write decimal numbers left to right with the largest digit first. A memory dump of a big-endian machine reads in the same order as the hex literal, which makes it pleasant for humans. Network protocols standardised on big-endian early, which is why it is also called network byte order.
Little-endian puts the little end first: the least significant byte goes at the lowest address. It looks backwards in a dump, but it has a quiet elegance — the byte at any address is always the 'ones' byte, so reading a value as a byte, a halfword, or a full word all start at the same place and just take more bytes. The x86 and most ARM systems you use every day are little-endian, so in practice little-endian is what your laptop almost certainly does.
store 32-bit 0x1A2B3C4D starting at address 100: address: 100 101 102 103 big-endian: 0x1A 0x2B 0x3C 0x4D (big end first) little-end: 0x4D 0x3C 0x2B 0x1A (little end first) read back as a byte at address 100: big-endian -> 0x1A little-endian -> 0x4D
Characters: from ASCII to Unicode and UTF-8
Numbers are not the only thing in memory — text is too, and text is just numbers under an agreed character encoding. The old ASCII scheme gave each English letter, digit, and punctuation mark a number from 0 to 127, fitting in 7 bits (so one byte, with the top bit spare). 'A' is 65 (0x41), 'a' is 97, '0' the digit is 48. That spare bit and the gaps in the table are why simple tricks work, like flipping one bit to switch a letter's case.
ASCII covers English and almost nothing else. Unicode fixed that by giving every character in every script — Latin, 中文, العربية, emoji — its own number, called a code point, with room for over a million of them. But a code point is an abstract number; you still have to turn it into bytes. The dominant way to do that is UTF-8, and its design is genuinely clever.
UTF-8 is a variable-length encoding: a character uses one to four bytes depending on its code point. The first 128 code points encode as a single byte identical to ASCII, so every ASCII file is already valid UTF-8 — a beautiful piece of backward compatibility. Larger code points use two, three, or four bytes, where the leading byte announces the length and the continuation bytes all begin with the bits 10, so you can tell at a glance whether a byte starts a character or continues one. The honest cost: you can no longer find 'the fifth character' by jumping five bytes, because characters are not all the same width.
Alignment: why the hardware likes tidy boundaries
Memory hands data to the processor not one byte at a time but in chunks — a word at a time, and at the cache level a whole cache line of perhaps 64 bytes. Because of this, the hardware strongly prefers each value to sit at an address that is a multiple of its own size: a 4-byte integer at an address divisible by 4, an 8-byte value at one divisible by 8. A value placed this way is aligned; this constraint is data alignment.
Why does it matter? An aligned 4-byte value falls entirely inside one memory word, so the hardware fetches it in a single access. A misaligned value can straddle two words — or even two cache lines — forcing two fetches and some shifting to stitch the halves together. On some processors a misaligned access is merely slow; on stricter ones it raises a fault and crashes. This is the same locality story from earlier rungs viewed up close: respecting boundaries lets each access ride one clean transfer.
This is why compilers insert invisible padding bytes inside structures. If a 1-byte field is followed by a 4-byte field, the compiler may leave 3 unused bytes after the first so the second lands on a multiple of 4. Reordering a struct's fields from largest to smallest can shrink it by removing padding — a small, real win that matters when you have millions of records. The padding is not waste the compiler forgot; it is the price of letting every field be fetched in one aligned access.
Reading a layout, end to end
Put the three ideas together and you can read any block of memory. Suppose a small record holds a 1-byte flag, then a 4-byte integer in little-endian, then a 3-character UTF-8 ASCII tag. Decoding it is a procedure, not a guess: you walk the bytes knowing the size of each field, the byte order of the numbers, the encoding of the text, and where the compiler slipped padding in to keep things aligned.
- Read 1 byte at offset 0 as the flag — single byte, so endianness does not apply.
- Skip 3 padding bytes (offsets 1 to 3) so the integer starts at offset 4, a multiple of 4 — that is alignment at work.
- Read 4 bytes at offset 4 and, since the machine is little-endian, reverse them to recover the integer's value.
- Read the next 3 bytes as code points 0 to 127, decoding each as one ASCII/UTF-8 character.
With this, the Data Representation rung is complete. You have travelled from raw bits and bytes through unsigned and two's-complement integers, the bit and shift tricks that make them fast, floating point and its honest imprecision, and finally how those values, plus text, sit ordered and aligned in real memory. Everything above this on the ladder — the datapath, the caches, virtual memory — manipulates exactly these byte patterns you can now read by hand.