ASCII defines 128 characters in seven bits, and only 95 of them are printable. The other 33 are control codes — carriage return, line feed, tab, bell, null — designed for teleprinters rather than screens, and several of them are still doing exactly the job they were specified for in 1963.
Everything above 127 is not ASCII. It depends on an encoding, which is where the UTF-8 article picks the story up.
Why seven bits and not eight?
Because the eighth bit was a parity bit on the serial links ASCII was designed for. Seven bits of data plus one of error checking fitted the hardware of the time, and the choice froze the character set at 128 slots.
That is why the extended sets of the 1980s — Latin-1, Windows-1252, the various code pages — all disagree above 127. Each one filled the newly free eighth bit differently, and a file gave no indication which had been used.
Where are the useful patterns in the table?
The layout is deliberate and worth knowing, because it makes several operations arithmetic rather than lookups.
| Range | Contents | Useful property |
|---|---|---|
| 0–31 | Control codes | Non-printing |
| 32–47 | Space and punctuation | Space is 32 |
| 48–57 | Digits 0–9 | Subtract 48 for the value |
| 65–90 | Upper case A–Z | |
| 97–122 | Lower case a–z | Exactly 32 above upper case |
The 32-place offset between cases is the neat one: A is 65 and a is 97, so flipping case is toggling a single bit. That is not a coincidence — the table was arranged so it would be true.
The digit range is the other: subtracting 48 turns the character 7 into the number 7, which is the whole of the simplest string-to-number conversion.
Why does padding matter?
Because without a fixed width the stream is ambiguous. The letter A is 1000001 in seven bits, and run together with the next character there is no way to know where one ends and the next begins.
Padding every character to eight bits fixes the boundaries and makes the result decodable. That is why binary text is conventionally written in bytes even when the values only need seven bits — 01001000 01101001 for "Hi" rather than the shorter form.
Hex has the same property for free: every byte is exactly two hex digits, so 48 65 6C 6C 6F is unambiguously "Hello" with no separator needed.
What happens above 127?
It depends on what you assume. A tool reading each value as a Unicode code point matches UTF-32 and matches what most people expect from a hex-to-text conversion — but a file that was actually Latin-1 will decode into different characters entirely.
That is the whole reason encodings have to be declared rather than guessed. A byte value of 233 is é in Latin-1, an invalid lead byte in UTF-8, and part of a different character in several code pages.
What is the difference between a character set and an encoding?
A character set says which characters exist and what number each one has. An encoding says how those numbers become bytes. ASCII is both at once, because its numbers fit in one byte each, and that coincidence is why the two words get used interchangeably.
Unicode separates them deliberately. It assigns a code point to every character — U+00E9 for é — and leaves UTF-8, UTF-16 and UTF-32 to disagree about how many bytes that takes. The code point is the identity; the encoding is the transport.
Which control codes still matter?
Four, in everyday work. Line feed (10) and carriage return (13) are the line-ending pair whose combinations still differ between platforms. Tab (9) is a delimiter in half the data formats in use. And null (0) terminates strings in C, which is the source of an entire category of security bug.
The rest are mostly historical, and a few are quietly delightful. Bell (7) still rings a terminal. Backspace (8), form feed (12) and vertical tab (11) describe motions of a print head that no longer exists.
Questions people ask
Is ASCII still relevant? As the first 128 code points of Unicode, yes — UTF-8 was designed so plain ASCII is byte-identical in both. A file of English text written in 1970 is a valid UTF-8 file today.
Why is space 32? So that it sits immediately below the printable punctuation and can be tested with a simple comparison. Anything below 32 is a control code.
What is the difference between a character and a byte? Nothing, in ASCII. Everything, once you go above 127 — which is precisely the confusion UTF-8 was designed to make manageable.
Does hex-to-text need an encoding? Yes, above 7F. Below it, every encoding agrees, which is why ASCII-range hex is unambiguous and nothing else is.
Why do line endings still differ? Because the two codes described physically different motions on a teleprinter — carriage return moved the head back, line feed advanced the paper. Unix chose one, Windows kept both, and the choice outlived the hardware by fifty years.
Seven bits, 95 printable characters, and a layout designed to make case and digits arithmetic. Hex to ASCII and ASCII to hex handle the byte pairs, ASCII to binary and binary to ASCII the padded bit form, and the binary translator covers what happens once you leave the first 128 slots.