Codifica UTF-16
UTF-16 (formato di trasformazione Unicode a 16 bit) è la codifica di caratteri a larghezza variabile che rappresenta i valori scalari Unicode mediante una o due unità di codice a 16 bit (2 o 4 byte). I caratteri del piano multilingue di base (U+0000 a U+D7FF e U+E000 a U+FFFF) sono mappati direttamente su una singola unità a 16 bit. I caratteri dei piani supplementari (U+10000 a U+10FFFF) — tra cui emoji, alfanumerici matematici e scritture storiche — sono codificati mediante una coppia ordinata di unità di codice riservate chiamata coppia surrogata.
Dati tecnici rapidi
U+0000–U+D7FF & U+E000–U+FFFF
Mappatura scalare diretta 1:1 (1 unità, 2 byte)
U+D800–U+DFFF
2,048 unità riservate; non sono caratteri scalari
U+10000–U+10FFFF
Codificati come coppie surrogate (2 unità, 4 byte)
U+FEFF)
BE: FE FF | LE: FF FE
Spazio di codice e distribuzione degli intervalli UTF-16
Lo standard Unicode partiziona l'intero spazio di $1,114,112$ punti di codice in piani. UTF-16 gestisce i punti di codice con singole unità a 16 bit per i caratteri scalari del BMP e coppie di unità a 16 bit per i caratteri supplementari, in conformità con la tabella 3-5 dello standard Unicode 18.0.
| Piano di caratteri | Intervallo scalare | Unità di codice | Lunghezza in byte | Intervallo unità di codice (hex) | Stato di codifica |
|---|---|---|---|---|---|
|
Basic Multilingual Plane (BMP, Lower)
Covers ASCII, Latin, Greek, Cyrillic, Hebrew, Arabic, and most common scripts.
|
U+0000–U+D7FF |
1 Unità | 2 Byte |
0000–D7FF |
Single Code Unit (Direct 1:1 scalar mapping) |
|
High-Surrogate Range (Lead Surrogates)
Permanently reserved for the leading unit of a surrogate pair. Cannot stand alone.
|
U+D800–U+DBFF |
1 Unità | 2 Byte |
D800–DBFF |
Reserved High Surrogates (Not Scalar Values) |
|
Low-Surrogate Range (Trail Surrogates)
Permanently reserved for the trailing unit of a surrogate pair. Cannot stand alone.
|
U+DC00–U+DFFF |
1 Unità | 2 Byte |
DC00–DFFF |
Reserved Low Surrogates (Not Scalar Values) |
|
Basic Multilingual Plane (BMP, Upper)
Private Use Area, CJK compatibility, alphabetic presentation forms, specials.
|
U+E000–U+FFFF |
1 Unità | 2 Byte |
E000–FFFF |
Single Code Unit (Direct 1:1 scalar mapping) |
|
Supplementary Planes (Planes 1–16)
Contains emojis, historic scripts (Linear B, Egyptian Hieroglyphs), musical notation, rare CJK ideographs.
|
U+10000–U+10FFFF |
2 Unità | 4 Byte |
D800 DC00 – DBFF DFFF |
Surrogate Pair Required (High Surrogate + Low Surrogate) |
Il meccanismo della coppia surrogata
Poiché una singola unità di codice a 16 bit può indirizzare al massimo $65,536$ valori, Unicode ha riservato $2,048$ unità di codice nel piano multilingue di base (piano 0) specificamente per codificare gli $1,048,576$ caratteri supplementari (piani 1–16).
0xD800–0xDBFF0xDC00–0xDFFF1. Formula di codifica (scalare verso surrogati)
Per qualsiasi punto di codice supplementare $C$ dove $0\text{x}10000 \le C \le 0\text{x}10\text{FFFF}$:
U' = C - 0x10000;HighSurrogate = 0xD800 + (U' >> 10);LowSurrogate = 0xDC00 + (U' & 0x3FF);
Sottrarre $0\text{x}10000$ produce un numero a 20 bit ($2^{20} = 1,048,576$). La suddivisione in due metà da 10 bit si inserisce perfettamente nelle due finestre surrogate da 1,024 unità.
2. Formula di decodifica (surrogati verso scalare)
Dati un surrogato alto valido $W_1$ e un surrogato basso valido $W_2$:
C = 0x10000 + ((W1 - 0xD800) << 10) + (W2 - 0xDC00);
Inverte gli shift di 10 bit e aggiunge l'offset $0\text{x}10000$ per ricostruire l'esatto valore scalare Unicode a 21 bit.
Ispettore e validatore UTF-16 interattivo
Esplora in tempo reale la codifica delle unità di codice UTF-16, alterna le serializzazioni di byte Big-Endian e Little-Endian, o inserisci unità di codice esadecimali grezze per validarne la conformità delle sequenze.
D83D DE00
D8 3D DE 00
3D D8 00 DE
0xD83D seguito dal surrogato basso 0xDE00, che insieme decodificano in U+1F600. Esempio svolto: codifica di 😀 (U+1F600)
Segui l'esatta derivazione matematica e di shifting di bit definita dallo standard Unicode 18.0 per convertire il valore scalare supplementare U+1F600 nella sua coppia surrogata UTF-16 D83D DE00.
0x1F600 - 0x10000 = 0x0F600
High 10 bits: 0x03D (0000111101) | Low 10 bits: 0x200 (1000000000)
0xD800 + 0x03D = 0xD83D
0xDC00 + 0x200 = 0xDE00
D83D DE00
Verifica mediante decodifica inversa
C = 0x10000 + ((0xD83D - 0xD800) << 10) + (0xDE00 - 0xDC00)
C = 0x10000 + (0x03D × 1024) + 0x200 = 0x10000 + 0xF400 + 0x200 = 0x1F600 (U+1F600) ✓
La formula inversa ricostruisce il valore scalare originale con una fedeltà matematica del 100%.
Esempi rappresentativi tra i piani
Caratteri Unicode rappresentativi, simboli matematici, scritture storiche, segni combinanti e sequenze emoji complesse codificati in UTF-16.
Latin Capital Letter A
ASCII / Basic Latin0041
00 41
41 00
1 code unit (2 bytes). Illustrates 16-bit BMP encoding where high byte is 0x00.
Latin Small Letter E with Acute
Latin-1 Supplement00E9
00 E9
E9 00
1 code unit (2 bytes). Precomposed BMP accented character.
Euro Sign
Currency Symbols20AC
20 AC
AC 20
1 code unit (2 bytes). Common BMP business character (0x20AC).
Infinity
Mathematical Operators221E
22 1E
1E 22
1 code unit (2 bytes). BMP mathematical symbol (0x221E).
Grinning Face
Emoji / SMPD83D DE00
D8 3D DE 00
3D D8 00 DE
2 code units (4 bytes). Canonical emoji surrogate pair: D83D DE00.
Linear B Ideogram B105F Mare
Historic Scripts (SMP)D800 DC83
D8 00 DC 83
00 D8 83 DC
2 code units (4 bytes). Tests high surrogate lower boundary (0xD800).
CJK Unified Ideographs Extension B
Rare CJK Ideograph (SIP)D869 DEA5
D8 69 DE A5
69 D8 A5 DE
2 code units (4 bytes). Plane 2 Ideograph: U+2A6A5 -> D869 DEA5.
Combining E + Acute Accent
Combining Sequence0065 0301
00 65 03 01
65 00 01 03
2 code points, 2 code units (4 bytes). 1 perceived glyph = 2 code units.
Woman Technologist
ZWJ Emoji SequenceD83D DC69 200D D83D DCBB
D8 3D DC 69 20 0D D8 3D DC BB
3D D8 69 DC 0D 20 3D D8 BB DC
3 code points, 5 UTF-16 code units (10 bytes). Complex sequence joined by ZWJ.
Ordine dei byte e serializzazione: UTF-16BE vs UTF-16LE
UTF-16 definisce una forma di codifica che usa unità di codice a 16 bit. Quando questi interi a 16 bit vengono serializzati in un flusso di byte a 8 bit (per trasmissione in rete o archiviazione), l'ordine dei due byte all'interno di ogni unità di codice è governato dallo schema di codifica: Big-Endian o Little-Endian.
| Carattere | Punto di codice | Unità di codice a 16 bit | UTF-16BE (Big-Endian) | UTF-16LE (Little-Endian) | Comportamento di serializzazione |
|---|---|---|---|---|---|
| A | U+0041 |
0041 |
00 41 |
41 00 |
ASCII: Big-Endian places 00 first; Little-Endian places 41 first. |
| € | U+20AC |
20AC |
20 AC |
AC 20 |
Euro Sign: Single code unit 20AC inverted in Little-Endian. |
| ∞ | U+221E |
221E |
22 1E |
1E 22 |
Infinity: Single code unit 221E inverted in Little-Endian. |
| 😀 | U+1F600 |
D83D DE00 |
D8 3D DE 00 |
3D D8 00 DE |
Emoji: Note that each 16-bit code unit is byte-swapped individually! |
| 𐂃 | U+10083 |
D800 DC83 |
D8 00 DC 83 |
00 D8 83 DC |
Historic script: D800 DC83 serialized to 00 D8 83 DC in Little-Endian. |
Nota importante sullo scambio dei surrogati
Serializzando una coppia surrogata in modalità Little-Endian (UTF-16LE), ogni unità di codice a 16 bit viene scambiata byte per byte individualmente. L'ordine delle due unità di codice rimane invariato: il surrogato alto precede sempre il surrogato basso. Ad esempio, D83D DE00 diventa 3D D8 00 DE, NON 00 DE 3D D8.
Semantica della marca d'ordine dei byte (BOM)
La marca d'ordine dei byte (BOM) è il carattere Unicode U+FEFF (SPAZIO UNIFICATORE SENZA INTERRUZIONE). Posta all'inizio di un flusso UTF-16 serializzato, il suo schema di byte rivela immediatamente se il flusso è Big-Endian o Little-Endian.
Il byte di ordine superiore 0xFE precede il byte di ordine inferiore 0xFF. Segnala un ordine dei byte Big-Endian.
Il byte di ordine inferiore 0xFF precede il byte di ordine superiore 0xFE. Segnala un ordine dei byte Little-Endian.
| Contesto del flusso | Stato del requisito | Spiegazione normativa |
|---|---|---|
| Explicitly Labeled Streams (e.g. charset=utf-16le or utf-16be) | Optional / Not Required | When the MIME type or transport layer explicitly declares the endianness, the byte order is already known. |
| Generic "UTF-16" Byte Streams (without BE/LE designation) | Recommended for Detection | If labeled simply "UTF-16", an initial BOM identifies whether the stream is Big-Endian (FE FF) or Little-Endian (FF FE). |
| Generic "UTF-16" Streams Lacking a BOM | Default to Big-Endian | Per RFC 2781 Section 4.3, in the absence of a BOM, systems without prior agreement should interpret generic UTF-16 as Big-Endian (UTF-16BE). |
| Mid-Stream Occurrence of U+FEFF | Treated as Zero-Width No-Break Space | If U+FEFF appears after the stream header, it is treated as a non-breaking space character, though U+2060 (Word Joiner) is preferred. |
Il mito del requisito universale
UTF-16 NON richiede universalmente una BOM. Sebbene sia comune nei file di testo Windows (come i file .txt del Blocco note etichettati "Unicode"), i protocolli che specificano charset=utf-16le o charset=utf-16be non la richiedono esplicitamente. Nelle applicazioni web, lo standard di codifica del WHATWG si basa su UTF-8, ma decodifica i flussi UTF-16 etichettati secondo la BOM esplicita o le definizioni MIME.
Buona formazione e sequenze surrogate malformate
Una sequenza di unità di codice UTF-16 è ben formata se e solo se ogni unità surrogata compare come parte di una sequenza correttamente appaiata e ordinata. Qualsiasi surrogato isolato o disallineato viola lo standard Unicode 18.0 §3.9 (definizione D92).
Invarianti di conformità Unicode
- Regola 1 (scalari del BMP): le singole unità di codice a 16 bit devono ricadere in
U+0000..U+D7FFoU+E000..U+FFFF. - Regola 2 (surrogati alti): qualsiasi surrogato alto (
0xD800..0xDBFF) deve essere immediatamente seguito da un surrogato basso (0xDC00..0xDFFF). - Regola 3 (surrogati bassi): qualsiasi surrogato basso (
0xDC00..0xDFFF) deve essere immediatamente preceduto da un surrogato alto (0xD800..0xDBFF). - Regola 4 (non-caratteri): i non-caratteri (come
U+FDD0..U+FDEF,U+FFFE,U+FFFF) sono valori scalari Unicode validi e non devono mai essere trattati come errori di surrogazione.
| Unità di codice (hex) | Classificazione dell'errore | Offset dell'errore | Diagnostica di conformità allo standard | Rischio di sicurezza e di analisi |
|---|---|---|---|---|
D800 |
UNPAIRED_HIGH_SURROGATE | Posizione 0 |
Isolated High Surrogate at end of sequence with no matching low surrogate. | String truncation vulnerability; decoders may discard or generate replacement characters (U+FFFD). |
D83D 0041 |
EXPECTED_LOW_SURROGATE | Posizione 1 |
High surrogate (D83D) followed by ASCII letter A (0041) instead of a low surrogate (DC00..DFFF). | Surrogate desynchronization; downstream parsers may misinterpret payload boundaries. |
DC00 |
UNPAIRED_LOW_SURROGATE | Posizione 0 |
Isolated Low Surrogate encountered without a preceding high surrogate. | Orphaned trailing surrogate; causes malformed string crashes in strict environments. |
DC00 D83D |
UNPAIRED_LOW_SURROGATE | Posizione 0 |
Inverted surrogate order: low surrogate (DC00) appears before high surrogate (D83D). | Surrogate inversion produces two ill-formed code units; rejected by standard decoders. |
D800 D800 |
EXPECTED_LOW_SURROGATE | Posizione 1 |
Two consecutive high surrogates; the first high surrogate is never completed. | Surrogate stacking error; common when slice operations cut strings through surrogate boundaries. |
0041 D83D |
TRUNCATED_SURROGATE_PAIR | Posizione 1 |
Valid ASCII A (0041) followed by high surrogate D83D truncated before its low surrogate. | Buffer cutoff at surrogate boundary. |
Concetti fondamentali e architettura
Distinzioni essenziali per implementare e fare debug correttamente delle stringhe UTF-16 nel software moderno.
Code Unit vs. Code Point vs. Byte
In UTF-16, a code unit is 16 bits (2 bytes). A code point is a numeric index in the Unicode codespace. In the BMP, 1 code point = 1 code unit = 2 bytes. In supplementary planes (e.g. 😀), 1 code point = 2 code units = 4 bytes.
User-Perceived Characters & Grapheme Clusters
A single visible character on screen can require more than one code point. For example, 👩💻 (Woman Technologist) consists of 3 code points (Woman U+1F469, ZWJ U+200D, Laptop U+1F4BB) and spans 5 UTF-16 code units (10 serialized bytes). Do not confuse code unit counts with human-perceived characters.
UTF-16 vs. UCS-2
UCS-2 was a legacy fixed-width 16-bit encoding that only supported the Basic Multilingual Plane (U+0000..U+FFFF). UCS-2 had no concept of surrogate pairs and could not represent characters beyond 0xFFFF. UTF-16 superseded UCS-2 by introducing surrogate pairs, enabling representation of all 1,114,112 Unicode code points.
UTF-16 vs. UTF-8
UTF-8 is an 8-bit byte-oriented variable-width encoding (1 to 4 bytes per scalar) that is strictly ASCII-compatible. UTF-16 is a 16-bit code-unit variable-width encoding (2 or 4 bytes per scalar). UTF-8 dominates the web, while UTF-16 is widely used as an in-memory string representation in operating systems and runtimes.
Programming String Length Pitfall (JS, Java, C#)
Many programming language string implementations (such as JavaScript "string".length, Java String.length(), and C# string.Length) count 16-bit UTF-16 code units rather than Unicode code points. Consequently, "😀".length reports 2 instead of 1. Use Array.from(str).length or code-point-aware iterators to count true characters.
Codifiche di caratteri correlate
Standard autorevoli e riferimenti normativi
Tutti i dati, i calcoli sui surrogati, le regole di buona formazione e gli ordini di serializzazione dei byte di questa pagina derivano direttamente da standard tecnici normativi:
- The Unicode Standard, Version 17.0 — Section 3.8 (Surrogates) & Section 3.9 (Unicode Encoding Forms - Table 3-5) (Unicode Consortium)
- RFC 2781 — UTF-16, an encoding of ISO 10646 (Internet Engineering Task Force (IETF))
- WHATWG Encoding Standard — Section 4.5 (utf-16be) & Section 4.6 (utf-16le) (Web Hypertext Application Technology Working Group (WHATWG))