# 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+-` | `&mdash;` | | – | En dash | `Alt+0150` | `Option+-` | `&ndash;` | | … | Ellipsis | `Alt+0133` | `Option+;` | `&hellip;` | | · | Middle dot | `Alt+0183` | `Option+Shift+9` | `&middot;` | | • | Bullet | `Alt+0149` | `Option+8` | `&bull;` | | ‘ ’ | Single quotes | `Alt+0145 / Alt+0146` | `Option+] / Option+Shift+]` | `&lsquo; &rsquo;` | | “ ” | Double quotes | `Alt+0147 / Alt+0148` | `Option+[ / Option+Shift+[` | `&ldquo; &rdquo;` | | « » | Guillemets | `Alt+0171 / Alt+0187` | `Option+\` / `Option+Shift+\` | `&laquo; &raquo;` | | © | Copyright | `Alt+0169` | `Option+G` | `&copy;` | | ® | Registered | `Alt+0174` | `Option+R` | `&reg;` | | ™ | Trademark | `Alt+0153` | `Option+2` | `&trade;` | | § | Section | `Alt+0167` | `Option+6` | `&sect;` | | ¶ | Pilcrow | `Alt+0182` | `Option+7` | `&para;` | | ° | Degree | `Alt+0176` | `Option+Shift+8` | `&deg;` | | ± | Plus-minus | `Alt+0177` | `Option+Shift+=` | `&plusmn;` | | × | Multiplication | `Alt+0215` | *(none by default)* | `&times;` | | ÷ | Division | `Alt+0247` | `Option+/` | `&divide;` | | ¼ ½ ¾ | Fractions | `Alt+0188 / 0189 / 0190` | *(none by default)* | `&frac14; &frac12; &frac34;` | | € | Euro | `Alt+0128` | `Option+Shift+2` | `&euro;` | | £ | Pound | `Alt+0163` | `Option+3` | `&pound;` | | ¥ | Yen | `Alt+0165` | `Option+Y` | `&yen;` | | ¢ | Cent | `Alt+0162` | `Option+4` | `&cent;` | | ¿ ¡ | Inverted marks | `Alt+0191 / Alt+0161` | `Option+Shift+? / Option+1` | `&iquest; &iexcl;` | | é | e acute | `Alt+0233` | `Option+E, then E` | `&eacute;` | | ñ | n tilde | `Alt+0241` | `Option+N, then N` | `&ntilde;` | | ü | u umlaut | `Alt+0252` | `Option+U, then U` | `&uuml;` | | ↑ ↓ → ← | Arrows | `Alt+24` / `25` / `26` / `27` *(no zero)* | *(use the character viewer)* | `&uarr; &darr; &rarr; &larr;` | ### 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 `&mdash;` 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]]