UTF-8 Encoding¶
UTF-8 (Unicode Transformation Format – 8-bit) is the most widely used character encoding in the world. It encodes all Unicode characters (over 1.1 million possible characters) in 1 to 4 bytes.
Basic Principle¶
Unicode assigns a unique number to every character – the code point (e.g. U+0041 = "A"). UTF-8 defines how this code point is stored as a sequence of bytes.
Key properties: - Variable length – 1 to 4 bytes per character - Backward-compatible with ASCII – the first 128 characters (U+0000–U+007F) are identical to ASCII (1 byte) - Self-synchronizing – the start of a character can be identified at any point in a byte stream - No byte-order issue – unlike UTF-16/UTF-32 (no BOM needed)
Byte Encoding by Code Point Range¶
| Code point range | Bytes | Byte pattern | Usable bits |
|---|---|---|---|
| U+0000 – U+007F | 1 | 0xxxxxxx |
7 bits |
| U+0080 – U+07FF | 2 | 110xxxxx 10xxxxxx |
11 bits |
| U+0800 – U+FFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
15 bits |
| U+10000 – U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
21 bits |
Explanation of the Bit Patterns¶
- First byte determines the total length:
0xxxxxxx→ 1-byte character (ASCII)110xxxxx→ 2-byte character (leading110)1110xxxx→ 3-byte character (leading1110)11110xxx→ 4-byte character (leading11110)- Continuation bytes always start with
10xxxxxx(marker: continuation byte) - The
xbits contain the actual code point value (big-endian)
Step by Step: Encoding a Character¶
Example 1: "A" (U+0041)¶
Code point: 0x0041 = 0b01000001
Range: U+0000–U+007F → 1 byte
Pattern: 0xxxxxxx
Result: 0b01000001 = 0x41
→ Identical to ASCII: 0x41
Example 2: "ä" (U+00E4)¶
Code point: 0x00E4 = 0b11100100
Range: U+0080–U+07FF → 2 bytes
Pattern: 110xxxxx 10xxxxxx
110 00011 10 100100
↑↑↑ ↑↑↑↑↑↑
upper 5 bits lower 6 bits of 0xE4
Result: 0b11000011 0b10100100 = 0xC3 0xA4
→ UTF-8: 0xC3 0xA4
Example 3: "€" (U+20AC)¶
Code point: 0x20AC = 0b0010 000010 101100
Range: U+0800–U+FFFF → 3 bytes
Pattern: 1110xxxx 10xxxxxx 10xxxxxx
1110 0010 10 000010 10 101100
Result: 0xE2 0x82 0xAC
→ UTF-8: 0xE2 0x82 0xAC
Example 4: 😀 Emoji (U+1F600)¶
Code point: 0x1F600 = 0b000 011111 011000 000000
Range: U+10000–U+10FFFF → 4 bytes
Pattern: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
11110 000 10 011111 10 011000 10 000000
Result: 0xF0 0x9F 0x98 0x80
→ UTF-8: 0xF0 0x9F 0x98 0x80
Self-Synchronization¶
A distinctive feature of UTF-8 is that the role of any given byte can be identified immediately:
| Byte value | Meaning |
|---|---|
0x00–0x7F (0xxxxxxx) |
Single ASCII character |
0xC0–0xDF (110xxxxx) |
Start of a 2-byte character |
0xE0–0xEF (1110xxxx) |
Start of a 3-byte character |
0xF0–0xF7 (11110xxx) |
Start of a 4-byte character |
0x80–0xBF (10xxxxxx) |
Continuation byte |
→ In the event of a transmission error, the receiver can reliably find the next valid character start by waiting for a byte that does not begin with 10.
Invalid Byte Sequences¶
UTF-8 explicitly defines forbidden sequences:
| Sequence | Problem |
|---|---|
0xFE, 0xFF |
Not defined in UTF-8 |
| Overlong encoding | e.g. 0xC0 0x80 for U+0000 (forbidden) |
Surrogate pairs U+D800–U+DFFF |
Reserved for UTF-16 only, illegal in UTF-8 |
| Code points > U+10FFFF | Outside the Unicode range |
| Standalone continuation byte | 10xxxxxx without a preceding lead byte |
BOM (Byte Order Mark)¶
UTF-8 does not need a BOM, since no byte order (endianness) needs to be specified. Some programs still insert EF BB BF at the start of a file – this is optional and can cause problems (e.g. in shell scripts).
Comparison: UTF-8, UTF-16, UTF-32¶
| Property | UTF-8 | UTF-16 | UTF-32 |
|---|---|---|---|
| Bytes per character | 1–4 | 2 or 4 | 4 (fixed) |
| ASCII-compatible | ✅ Yes | ❌ No | ❌ No |
| BOM required | No | Yes (LE/BE) | Yes (LE/BE) |
| Memory usage (Latin) | Low (1 byte) | Medium (2 bytes) | High (4 bytes) |
| Memory usage (CJK) | Medium (3 bytes) | Low (2 bytes) | High (4 bytes) |
| Self-synchronizing | ✅ Yes | ❌ No | ✅ Yes |
| Usage share (web) | ~98% | Rare | Rare |
Taskit Port Encoding (Extension)¶
The taskit gpio.net protocol uses a UTF-8-inspired encoding for port commands:
| Mode | Range | Encoding |
|---|---|---|
| Nibble Mode | 0x00–0x7F | '0' C2 C1 C0 D3 D2 D1 D0 – 4-bit data |
| Byte Mode | 0x80–0x7FF | '110' C2 C1 C0 D7 D6 '10' D5..D0 – 8-bit data |
| Not used | 0x800–0xFFFF | reserved |
| Word Mode / Extended | 0x10000–0x10FFFF | '11110' C2..C0 '10' C4 C3 D15..D12 '10' D11..D6 '10' D5..D0 – 16-bit data |
→ C = command/event bit · D = data bit · structure analogous to UTF-8 lead bytes
See also: portchar_260514.key
References¶
- RFC 3629 – UTF-8, a transformation format of ISO 10646
- Unicode Standard: https://www.unicode.org/standard/standard.html
- Wikipedia: https://en.wikipedia.org/wiki/UTF-8