Data representation in memory
1. Memory as a Numbered Array of Bytes
Main memory is a linear sequence of byte cells, each with a unique address. Data is nothing but bit patterns stored in one or more consecutive bytes; the interpretation (as integer, float, character or instruction) comes from the program, not from the memory. For a 32-bit machine with a 4 GB address space:
2. Typical Layout of Data Types
Sizes depend on the machine, but on a common 64-bit (LP64/LLP64) system:
| Type | Size | How it is stored |
|---|---|---|
char |
1 byte | ASCII/UTF-8 code |
short |
2 bytes | 2's complement integer |
int |
4 bytes | 2's complement integer |
long long |
8 bytes | 2's complement integer |
float |
4 bytes | IEEE-754 single precision (1 + 8 + 23) |
double |
8 bytes | IEEE-754 double precision (1 + 11 + 52) |
| pointer / address | 8 bytes on 64-bit, 4 on 32-bit | Unsigned address value |
| array of n ints | 4n bytes | Contiguous, element i at base + 4i |
| string "abc" | 4 bytes | 'a','b','c' plus a null terminator (C style) |
| struct | sum of members + padding | Members in declaration order with alignment gaps |
3. Address Arithmetic
For an array of elements of size starting at base address :
Example: int a[10] starting at address 1000 (4-byte ints):
| Element | a[0] | a[1] | a[2] | a[3] | … | a[9] |
|---|---|---|---|---|---|---|
| Address | 1000 | 1004 | 1008 | 1012 | … | 1036 |
The whole array occupies bytes. This linear formula is exactly why array indexing is a single multiply-and-add instruction, and why bounds checking is the programmer's job in C.
4. How a Mixed Structure Looks in Memory (little-endian)
int x = 0x12345678; /* 4 bytes */
char c = 'A'; /* 1 byte */
int y = -1; /* 4 bytes */
On a big-endian machine the same x would appear as 12 34 56 78, while y would still be FF FF FF FF — only the byte order of multi-byte values changes.
5. Alignment and Padding
CPUs read memory word-by-word, so an object is normally placed at an address that is a multiple of its size (natural alignment); the compiler inserts padding bytes to satisfy this.
struct S { char a; int b; char c; };
| Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8-11 | 12-15 |
|---|---|---|---|---|---|---|---|---|---|---|
| Content | a | pad | pad | pad | b | b | b | b | c + 3 pad | (struct padded to a multiple of 4) |
sizeof(struct S) = 16, not 6. Why it matters: misaligned access may take two memory cycles (or trap on some architectures), and the padding trade-off is a classic exam question. Declaring members in decreasing order of size often reduces the wasted bytes.
6. Memory Segments of a Running Program (process image)
HIGH ADDRESSES
┌──────────────────────┐
│ STACK │ ← local variables, parameters, return addresses
│ grows DOWN ↓ │ (one frame per function call; SP tracks the top)
├──────────────────────┤
│ free gap │
├──────────────────────┤
│ HEAP │ ← dynamic memory (malloc / new)
│ grows UP ↑ │
├──────────────────────┤
│ BSS │ ← uninitialised global/static variables (zero-filled)
├──────────────────────┤
│ DATA (initialised) │ ← globals/statics with an initial value
├──────────────────────┤
│ TEXT (code) │ ← the machine instructions, read-only
└──────────────────────┘
LOW ADDRESSES
Knowing this layout explains common phenomena: stack overflow from deep recursion, heap exhaustion from memory leaks, and why writing to a string literal (which lives in TEXT) crashes the program.
7. Bits Inside a Word — Packing, Flags and I-O
- Bit flags — 8 boolean options fit in one byte:
bit: 7 6 5 4 3 2 1 0
READ WRITE EXEC DEL COPY ... ... ...
value 0/1 each → status = (1<<READ) | (1<<EXEC) = 0x81
- Bit fields and bitwise operators (
&,|,^,~,<<,>>) read and set individual bits without touching their neighbours. - Memory-mapped I/O — hardware registers (UART data, GPIO port, timer) appear as ordinary memory addresses, so a store to address 0x4000_0000 can switch on an LED.
- Floating point in memory: the same 32 bits are split into sign, biased exponent and mantissa, so
12.5=0x41480000— reading those bytes as an integer gives 1094713344, which is why type punning requires care.
8. Exam Points
- How are integers, characters, floats and strings represented in memory? — 5 marks, frequent.
- Compute the address of
a[i]given the base address and element size — 3-5 marks numerical. - Draw the byte-by-byte memory map of a small declaration (with endianness) — 5 marks.
- Explain alignment and padding with a struct example — 5 marks.
- Draw the memory layout of a running program (text, data, BSS, heap, stack) — 5-7 marks, very frequent.
- How are multiple flags packed into one byte? Give an example — 3 marks.