# ASCII and Hotkeys
> [!abstract] What this note is
> Two references that turn out to be the same subject. First, the **ASCII table**, and the reason `Ctrl+C`, `Ctrl+M` and `Ctrl+[` do what they do. Second, the **hotkeys for typing characters that aren't on the keyboard**, on Windows and Mac, which are not ASCII at all, and it helps to know why.
## The one rule behind every Ctrl hotkey
ASCII has 128 codes. The first 32 are **control characters**: instructions to a teletype rather than marks on paper. A keyboard had no keys for them, so the designers added a modifier that subtracts.
**`Ctrl` takes the code of the key you press and subtracts 64.**
```
M = 77 = 100 1101
Ctrl+M = 13 = 000 1101 → carriage return, which is Enter
```
That single rule explains the oddities people memorise as trivia:
- `Ctrl+M` is **Enter**, because M is 77 and carriage return is 13
- `Ctrl+I` is **Tab**, because I is 73 and horizontal tab is 9
- `Ctrl+[` is **Esc**, because `[` is 91 and escape is 27. Vim users lean on this one
- `Ctrl+H` is **Backspace**, because H is 72 and backspace is 8
- `Ctrl+C` interrupts because 3 is *end of text*, and `Ctrl+D` closes a shell because 4 is *end of transmission*
A terminal cannot tell `Ctrl+M` from Enter, or `Ctrl+I` from Tab. They are the same byte. That is why some key combinations can't be bound separately in terminal programs.
## Control characters and their hotkeys
| Hotkey | Dec | Hex | Name | Meaning | What it does in a terminal |
|---|---|---|---|---|---|
| `Ctrl+@` | 0 | 00 | NUL | Null | |
| `Ctrl+A` | 1 | 01 | SOH | Start of heading | Shell: jump to start of line |
| `Ctrl+B` | 2 | 02 | STX | Start of text | Shell: back one character |
| `Ctrl+C` | 3 | 03 | ETX | End of text | **Interrupt** the running program |
| `Ctrl+D` | 4 | 04 | EOT | End of transmission | **End of input** on Unix; closes a shell |
| `Ctrl+E` | 5 | 05 | ENQ | Enquiry | Shell: jump to end of line |
| `Ctrl+F` | 6 | 06 | ACK | Acknowledge | Shell: forward one character |
| `Ctrl+G` | 7 | 07 | BEL | Bell | Rings the terminal bell |
| `Ctrl+H` | 8 | 08 | BS | Backspace | **Same as Backspace** |
| `Ctrl+I` | 9 | 09 | HT | Horizontal tab | **Same as Tab** |
| `Ctrl+J` | 10 | 0A | LF | Line feed | Newline (Unix line ending) |
| `Ctrl+K` | 11 | 0B | VT | Vertical tab | Shell: cut to end of line |
| `Ctrl+L` | 12 | 0C | FF | Form feed | **Clear the screen** |
| `Ctrl+M` | 13 | 0D | CR | Carriage return | **Same as Enter** |
| `Ctrl+N` | 14 | 0E | SO | Shift out | Shell: next history entry |
| `Ctrl+O` | 15 | 0F | SI | Shift in | |
| `Ctrl+P` | 16 | 10 | DLE | Data link escape | Shell: previous history entry |
| `Ctrl+Q` | 17 | 11 | DC1 | Device control 1 (XON) | **Resume** output paused by Ctrl+S |
| `Ctrl+R` | 18 | 12 | DC2 | Device control 2 | Shell: search history backwards |
| `Ctrl+S` | 19 | 13 | DC3 | Device control 3 (XOFF) | **Pause** terminal output. Looks like a freeze; Ctrl+Q undoes it |
| `Ctrl+T` | 20 | 14 | DC4 | Device control 4 | Shell: swap two characters |
| `Ctrl+U` | 21 | 15 | NAK | Negative acknowledge | Shell: delete to start of line |
| `Ctrl+V` | 22 | 16 | SYN | Synchronous idle | Shell: insert the next key literally |
| `Ctrl+W` | 23 | 17 | ETB | End of transmission block | Shell: delete the previous word |
| `Ctrl+X` | 24 | 18 | CAN | Cancel | |
| `Ctrl+Y` | 25 | 19 | EM | End of medium | Shell: paste what Ctrl+K or Ctrl+U cut |
| `Ctrl+Z` | 26 | 1A | SUB | Substitute | **Suspend** on Unix; **end of input** in the Windows console |
| `Ctrl+[` | 27 | 1B | ESC | Escape | **Same as Esc** |
| `Ctrl+\` | 28 | 1C | FS | File separator | Unix: quit with a core dump |
| `Ctrl+]` | 29 | 1D | GS | Group separator | Telnet's escape key |
| `Ctrl+^` | 30 | 1E | RS | Record separator | |
| `Ctrl+_` | 31 | 1F | US | Unit separator | Shell: undo |
| `Ctrl+?` | 127 | 7F | DEL | Delete | What the Backspace key sends on many terminals |
> [!tip] The freeze that isn't
> `Ctrl+S` pauses output in most terminals, and the screen simply stops. It is the single most common "my terminal crashed" report. `Ctrl+Q` resumes it.
Shell editing keys are the defaults for bash and zsh in Emacs mode. Graphical applications reuse the same combinations for unrelated things (`Ctrl+C` copy, `Ctrl+V` paste, `Ctrl+Z` undo), which is why copy and paste in a terminal usually need `Ctrl+Shift`.
## The printable characters
Codes 32 to 126. Read the row for the first hex digit and the column for the second: `A` is row `4_`, column `_1`, so hex 41, decimal 65.
```
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _E _F
2_ SP ! " # $ % & ' ( ) * + , - . /
3_ 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4_ @ A B C D E F G H I J K L M N O
5_ P Q R S T U V W X Y Z [ \ ] ^ _
6_ ` a b c d e f g h i j k l m n o
7_ p q r s t u v w x y z { | } ~ DEL
```
Two patterns worth knowing:
- **Upper and lower case differ by exactly 32**, one bit. `A` is 65 and `a` is 97. Case conversion in old code is a single bit flip
- **The digits start at 48**, so the character `7` minus 48 is the number 7. That subtraction appears in a great deal of parsing code
## Characters that are not on the keyboard
Everything in this section is **beyond ASCII**. ASCII stops at 127 and has no em dash, no curly quotes and no accented letters. These characters come from Windows-1252 and Unicode, which is why typing them needs a different mechanism on each system.
| Char | Name | Windows | Mac | HTML entity |
|---|---|---|---|---|
| — | Em dash | `Alt+0151` | `Option+Shift+-` | `—` |
| – | En dash | `Alt+0150` | `Option+-` | `–` |
| … | Ellipsis | `Alt+0133` | `Option+;` | `…` |
| · | Middle dot | `Alt+0183` | `Option+Shift+9` | `·` |
| • | Bullet | `Alt+0149` | `Option+8` | `•` |
| ‘ ’ | Single quotes | `Alt+0145 / Alt+0146` | `Option+] / Option+Shift+]` | `‘ ’` |
| “ ” | Double quotes | `Alt+0147 / Alt+0148` | `Option+[ / Option+Shift+[` | `“ ”` |
| « » | Guillemets | `Alt+0171 / Alt+0187` | `Option+\` / `Option+Shift+\` | `« »` |
| © | Copyright | `Alt+0169` | `Option+G` | `©` |
| ® | Registered | `Alt+0174` | `Option+R` | `®` |
| ™ | Trademark | `Alt+0153` | `Option+2` | `™` |
| § | Section | `Alt+0167` | `Option+6` | `§` |
| ¶ | Pilcrow | `Alt+0182` | `Option+7` | `¶` |
| ° | Degree | `Alt+0176` | `Option+Shift+8` | `°` |
| ± | Plus-minus | `Alt+0177` | `Option+Shift+=` | `±` |
| × | Multiplication | `Alt+0215` | *(none by default)* | `×` |
| ÷ | Division | `Alt+0247` | `Option+/` | `÷` |
| ¼ ½ ¾ | Fractions | `Alt+0188 / 0189 / 0190` | *(none by default)* | `¼ ½ ¾` |
| € | Euro | `Alt+0128` | `Option+Shift+2` | `€` |
| £ | Pound | `Alt+0163` | `Option+3` | `£` |
| ¥ | Yen | `Alt+0165` | `Option+Y` | `¥` |
| ¢ | Cent | `Alt+0162` | `Option+4` | `¢` |
| ¿ ¡ | Inverted marks | `Alt+0191 / Alt+0161` | `Option+Shift+? / Option+1` | `¿ ¡` |
| é | e acute | `Alt+0233` | `Option+E, then E` | `é` |
| ñ | n tilde | `Alt+0241` | `Option+N, then N` | `ñ` |
| ü | u umlaut | `Alt+0252` | `Option+U, then U` | `ü` |
| ↑ ↓ → ← | Arrows | `Alt+24` / `25` / `26` / `27` *(no zero)* | *(use the character viewer)* | `↑ ↓ → ←` |
### How the Windows codes work
Hold `Alt`, type the digits **on the numeric keypad** with Num Lock on, release `Alt`.
**The leading zero matters.** `Alt+0151` gives an em dash, from the Windows code page. `Alt+151` without the zero reaches back to the old MS-DOS character set and gives a different character entirely. The arrows in the table are the exception that proves it: they exist only in the DOS set, so they are typed *without* a zero.
No numeric keypad? `Win+.` opens the emoji and symbol picker, and `Win+V` opens clipboard history.
### How the Mac codes work
`Option` is a second shift key. Accents are **dead keys**: `Option+E` types nothing and waits, then the next letter arrives wearing the accent. `Ctrl+Cmd+Space` opens the character viewer for everything else.
### In Markdown
The HTML entities in the last column work anywhere Markdown renders, including this vault. Typing `—` produces —. It is the only method that doesn't depend on the keyboard or the operating system. See [[Markdown Basics]].
## Sources
1. [RFC 20 — ASCII format for Network Interchange, 1969](https://www.rfc-editor.org/rfc/rfc20) — primary: the code table and control character names
2. [Alt code — Wikipedia](https://en.wikipedia.org/wiki/Alt_code) — reputable secondary: the leading-zero rule and the code page 437 arrows, checked 2026-09-21
3. [Windows-1252 — Wikipedia](https://en.wikipedia.org/wiki/Windows-1252) — reputable secondary: the code page behind the `Alt+0###` codes
*The Mac combinations and shell key bindings are written from working knowledge of the US keyboard layout and default bash and zsh settings, and were not checked against a source. Other layouts differ.*
## Related
- [[Markdown Reference Index]] — the rest of the Markdown course
- [[Markdown Basics]] · [[Footnotes Comments and Escapes]]