Utf-8, quanti byte per una lettera?

La memoria di un computer è fatta di byte. Ogni byte è un insieme di otto bit. Ogni bit può avere il valore di 1 o di 0. Quindi in ogni byte ci sono 256 possibilità, abbastanza per memorizzare un numero qualsiasi tra 0 e 255, secondo le regole dell’aritmetica booleana.

Per memorizzare un testo basta associare un numero ben preciso a ciascuna lettera dell’alfabeto, segno di interpunzione, simbolo matematico. L’alfabeto è di 26 lettere, ognuna delle quali è disponibile in due versioni, maiuscola e minuscola. In teoria 128 codici diversi bastano e avanzano. E infatti sui primi computer bastava un byte per ciascuna lettera. La parola “ciao” occupava quattro byte di memoria.

Però ci sono varie complicazioni. Prima di tutto ogni lettera accentata ha bisogno di un codice a sé. In Italia si accentano almeno sei vocali, in minuscolo e in maiuscolo, e così abbiamo bisogno di 12 codici in più. In Spagna si usa una n sovrastata da una tilde, in Francia la c con la cedille, in Germania la doppia s o la dieresi sulla o, in Danimarca la o barrata... I 256 codici cominciano ad essere pochi.

Ma non esiste soltanto l’alfabeto latino: c’è il greco, l’arabo, l’ebraico, il cirillico, il devanagari. Ci sono migliaia di ideogrammi cinesi. Per non parlare delle scritture scomparse, come i geroglifici o la scrittura cuneiforme. È stato quindi ideato lo standard Unicode, che assegna un codice univoco a ciascuno dei simboli di tutte le scritture esistenti (emoji comprese). Ovviamente stiamo parlando di numeri molto alti, per ottenere i quali bisogna combinare insieme vari byte. Con due byte si avrebbero, in teoria, 256 possibilità al quadrato, con tre 256 al cubo e così via.

Assegnare quattro byte a ciascuna lettera dell’alfabeto però comporta due problemi. Il primo è uno spreco di memoria enorme. La parola “ciao” non occuperebbe più 4 byte di memoria, ma 16 (cioè 4 per lettera). Di cui i primi tre varrebbero 0, come per tutte le altre lettere dell’alfabeto latino. Sarebbe una scelta insensata. Il secondo problema è che si perderebbe la compatibilità con tutti i programmi scritti in precedenza, nei quali ad ogni lettera corrispondeva un byte.

La soluzione proposta dagli scienziati informatici è stata quella di codificare ancora le lettere latine in un byte, usandone due, o tre, o quattro per gli altri alfabeti a seconda delle esigenze.

C’era però un problema da risolvere: come fare per spiegare al software se una sequenza di 4 byte va interpretata come una parola di quattro lettere da un byte, o due lettere da due byte ciascuna, o una lettera da quattro byte?

La soluzione è stata molto ingegnosa. Nella codifica Utf-8, tutti i numeri da 0 a 127 vengono interpretati come caratteri di un byte. Ad esempio 97 è il codice della a minuscola (98 la b, eccetera). 65 è una A maiuscola (66 la B e così via, in ordine alfabetico).

I numeri tra 192 e 223 vengono interpretati come primo byte di una lettera da due byte. Quando il software trova il numero 206 sa che deve leggere anche il byte successivo, che deve essere un byte di continuazione, di valore tra 128 e 191. Se trova 177 nel byte successivo, allora scrive la lettera alfa dell’alfabeto greco. Questa lettere infatti è la numero 945, e il codice corrispondente non potrebbe rientrare in un byte di memoria dove il valore massimo è 255.

I numeri tra 224 e 239 indicano il primo byte di un carattere che occupa ne occupa 3, quindi il software si aspetta due byte di continuazione (di nuovo di valore tra 128 e 191).

I numeri tra 240 e 247 indicano il primo byte di un carattere da quattro byte, quindi ci si aspettano 3 byte di continuazione.

Questo sistema permette di saltare da un alfabeto all’altro senza dover specificare ogni volta che si sta passando da uno a due byte. Inoltre se per qualche motivo (ad esempio un disturbo in fase di trasmissione) alcuni byte dovessero andare persi, il software potrebbe ricominciare correttamente la decodifica appena ricomincia il flusso di dati, perché saprebbe in ogni momento se ogni byte che arriva rappresenta un carattere a sé, la continuazione di un carattere di cui non si conosce l’inizio, o l’inizio di un nuovo carattere.

Per esempio prendiamo questi sei byte: 206, 177, 97, 226, 152, 186. A quanti simboli corrispondono? Il primo byte è compreso tra 192 e 223, quindi vuol dire che fa parte di un carattere di due byte e va letto insieme al secondo. 206-177 è la lettera alfa dell’alfabeto greco. Il terzo, 97, è minore di 127 quindi va letto da solo: è la a dell’alfabeto latino. Il successivo, 226, è compreso tra 224 e 239, quindi vuol dire che è il primo di tre: va letto con i successivi, che devono entrambi essere compresi tra 128 e 191. Tutto corretto, e viene fuori che si tratta del carattere smile, ossia la faccina che sorride. Quindi questa sequenza di sei byte rappresenta soltanto tre caratteri: αa☺.

Se viene aggiunto un byte di valore 97 al terzo posto (206, 177, 97, 97, 226, 152, 186), la sequenza è ancora valida. È un carattere da un byte che compare dopo la fine di un carattere da 2 e prima di un carattere da 1. In pratica si tratta di una a in più.

Se invece lo aggiungiamo al secondo posto (206, 97, 177, 97, 226, 152, 186), la sequenza non è più valida. Il primo byte presuppone un byte di continuazione, e 97 non lo è, visto che è minore di 128. Il byte successivo, 177, è un byte di continuazione. Ma il precedente non è un byte di inizio. Insomma i primi tre byte sono indecifrabili. Dal successivo in poi però è tutto regolare, quindi la a e la faccina verrebbero interpretate correttamente.

Tutte queste regole non dipendono direttamente da Unicode, ma dalla codifica Utf-8, che è quella maggiormente usata sul web, in Occidente. Esistono altre codifiche, come la utf-16, che distribuiscono i valori Unicode nei byte in maniera diversa. Per l’alfabeto latino la utf-16 non conviene, perché i testi occuperebbero più spazio, ma per il cinese è più conveniente.

Infine ricordiamo che non necessariamente ai byte di informazione corrispondono byte di memoria, visto che i dati possono essere compressi dai software in fase di memorizzazione o di trasmissione via internet. Insomma, questo questo post, che è lungo 6 mila caratteri da un byte, può essere zippato in un file da 3 kilobyte di memoria senza perdere neanche un bit informazione.

Tutto questo c’entra qualcosa con i font? Solo indirettamente. In un file di testo (.txt) non è memorizzata la forma delle lettere, ma solo i codici di ciascuna lettera utilizzata. La forma per visualizzarle viene attinta a parte, nei font di sistema. Se una lettera non è supportata dai font installati sul dispositivo dell’utente, il software riconosce di quanti byte è composta, ma la visualizza come un quadratino vuoto, un punto interrogativo o un simbolo alternativo. Lo stesso testo può essere visualizzato in maniera diversa a seconda se lo si vede sul pc, sullo smartphone o sul Kindle, a seconda dei font installati.

Anche in una pagina web sono contenuti solo i codici delle lettere che devono essere visualizzate, ma ci sono anche le istruzioni per il browser su dove trovare o scaricare il font per visualizzare il testo nello stile giusto.

Commenti

Post più popolari