a cache line
When you fetch a book from a distant shelf, it is wasteful to make the whole trip for a single page. You bring back the entire book — and often a few neighbours too — because the trip is the expensive part, not the carrying. A cache line is the computer's version of 'don't make a long trip for one byte': it is the fixed-size chunk of memory that a cache moves and stores as one unit, typically 32, 64, or 128 bytes.
Memory is conceptually divided into equal-sized, aligned blocks. A 64-byte line, for example, covers a 64-byte-aligned span like addresses 0..63, then 64..127, and so on. When any byte in a block is needed and missing, the cache fetches the whole block at once and stores it together with a tag recording which memory region it holds. This is precisely how a cache cashes in on spatial locality: bringing in the neighbours of the byte you asked for means the next few accesses, which locality says are likely nearby, become hits for free. The lower bits of an address (the offset) just pick which byte within the line you want.
Line size is a real tradeoff. Bigger lines exploit spatial locality more (one miss brings more useful neighbours) and amortize the fixed cost of a memory trip over more bytes, but they waste bandwidth and cache space when locality is poor (you drag in neighbours you never use) and they can increase conflict misses. A subtle and important consequence appears with multiple cores: because sharing happens at line granularity, two cores updating different variables that happen to share one line ping-pong the whole line between them — the performance trap called false sharing (a coherence-level concern, noted here only so you know the unit of sharing is the line, not the byte).
On a 64-byte line, a 32-bit address splits its low 6 bits as the offset (2^6 = 64 byte positions within the line). Touching byte 0x1004 brings in the line covering 0x1000..0x103F; later accesses to 0x1008 or 0x1020 are then hits.
The fixed-size unit a cache moves as one block; fetching neighbours is how it banks spatial locality.
The cache never holds a single byte in isolation — it always holds whole lines. This is why one stray access can pull in 63 bytes you didn't ask for, and why scattering related data across many lines wrecks performance even when the total data is small.