The non-printing side of ASCII
The first 32 ASCII codes (0–31), plus DEL at 127, are control characters: they do not display a glyph but instead instruct the device to perform an action such as advancing a line, sounding a bell, or interrupting a program. This reference lists every C0 control character with its decimal and hex value, caret notation, C escape sequence where one exists, abbreviation, full name, and a note on its use.
Where control characters come from
Control characters were designed in the 1960s for teletype machines and early terminals, where communication channels needed in-band signalling to control paper advancing, cursor movement, and device state. The ASCII standard (ANSI X3.4-1963, revised 1967 and 1968) codified the C0 set: 32 control codes plus DEL, covering everything from flow control (XON/XOFF) to media navigation (FS, GS, RS, US) to character encoding state (SO/SI for switching character sets).
Most of the original use cases for control characters are obsolete — no one is advancing paper rolls anymore. But many survive in daily use:
| Character | Code | Still used for |
|---|---|---|
| NUL | 0 | String terminator in C, null byte in binary protocols |
| BEL | 7 | Terminal alerts; still triggers a beep or visual bell |
| BS | 8 | Backspace in text input |
| HT | 9 | Tab character in text, source code, TSV data |
| LF | 10 | Line ending on Unix/macOS/Linux |
| CR | 13 | Part of CRLF line ending on Windows; line ending in HTTP headers |
| ESC | 27 | Start of ANSI/VT100 terminal escape sequences |
| DEL | 127 | Forward-delete key in many terminals |
How caret notation maps to keys
Caret notation represents each control character as ^ followed by an uppercase
letter. The rule is simple: the caret letter’s ASCII code is the control
character’s code plus 64. So:
^A = code 1 (Ctrl+A, SOH — Start of Heading)
^C = code 3 (Ctrl+C, ETX — signals terminal interrupt / SIGINT)
^D = code 4 (Ctrl+D, EOT — signals end-of-file in many Unix programs)
^G = code 7 (Ctrl+G, BEL — audible bell)
^H = code 8 (Ctrl+H, BS — backspace)
^I = code 9 (Ctrl+I, HT — horizontal tab)
^J = code 10 (Ctrl+J, LF — newline, same as Enter in many contexts)
^M = code 13 (Ctrl+M, CR — carriage return)
^[ = code 27 (Ctrl+[, ESC — same key as Escape)
^? = code 127 (DEL — this is the special case; DEL = 64+63 = ^_ is unused)
The ^? for DEL is an exception: DEL (127) does not follow the +64 formula; it
is assigned ^? by convention because 127 mod 64 = 63 = ?.
LF versus CR versus CRLF — the line ending wars
Line endings are the most common place developers encounter control characters:
- Unix / macOS / Linux: LF only (
\n, code 10). This is the POSIX standard. - Windows: CRLF (
\r\n, codes 13 then 10). Inherited from teletype convention. - Classic Mac OS (before OS X): CR only (
\r, code 13). Changed to LF with OS X. - HTTP headers: CRLF is required by the HTTP specification, regardless of OS.
- Network protocols (SMTP, FTP): CRLF by RFC convention.
The mismatch between Unix and Windows line endings causes frequent problems with
Git, text editors, shell scripts, and diff tools. Git’s core.autocrlf setting
and the .gitattributes file exist specifically to handle this.
ESC and ANSI escape sequences
ESC (27, \x1b, \033 in octal) is the gateway to all ANSI/VT100 terminal
control sequences — cursor movement, colour output, screen clearing, and more.
An ANSI escape sequence begins with ESC and is followed by [ (the CSI
introducer) and a sequence of parameters ending in a letter:
ESC[0m — reset all formatting
ESC[1m — bold
ESC[31m — red foreground
ESC[2J — clear screen
ESC[H — move cursor to home position
Understanding that ESC starts these sequences explains why pressing Escape in a terminal sometimes causes a brief delay: the terminal is waiting to see whether ESC is the start of a sequence or a standalone key press.
How the reference is searched
The search matches any of the fields at once: decimal code, hex code, abbreviation
(like LF, ETX), full name (“Line Feed”), C escape sequence (\n), or caret
notation (^J). This makes it easy to look up a character whether you encountered
it as a decimal in a hex dump, a caret notation in a keystroke description, or a
backslash escape in source code.