(1) Cosa significa sequenza di byte, un arrary di char in C? UTF-16 è una sequenza di byte o che cos'è allora? (2) Perché una sequenza di byte non ha nulla a che fare con la lunghezza variabile?
Sembra che tu abbia frainteso quali siano le problematiche endian. Ecco un breve riassunto.
Un numero intero a 32 bit occupa 4 byte. Ora conosciamo l'ordinamento logico di questi byte. Se hai un numero intero a 32 bit, puoi ottenere il byte alto di questo con il seguente codice:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
Va tutto bene. Dove inizia il problema è come i vari hardware memorizzano e recuperano numeri interi dalla memoria.
In ordine Big Endian, un pezzo di memoria di 4 byte che leggi come numero intero a 32 bit verrà letto con il primo byte che è il byte alto:
[0][1][2][3]
Nell'ordine di Little Endian, un pezzo di memoria di 4 byte che leggi come numero intero a 32 bit verrà letto con il primo byte come byte basso :
[3][2][1][0]
Se si dispone di un puntatore a un puntatore a un valore a 32 bit, è possibile effettuare ciò:
uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?
Secondo C / C ++, il risultato non è definito. Potrebbe essere 0x81. O potrebbe essere 0x32. Tecnicamente, potrebbe restituire qualsiasi cosa, ma per i sistemi reali, restituirà l'uno o l'altro.
Se si dispone di un puntatore a un indirizzo di memoria, è possibile leggere tale indirizzo come valore a 32 bit, valore a 16 bit o valore a 8 bit. Su una macchina big endian, il puntatore punta al byte alto; su una piccola macchina endian, il puntatore punta al byte basso.
Si noti che si tratta solo di leggere e scrivere nella / dalla memoria. Non ha nulla a che fare con il codice C / C ++ interno. La prima versione del codice, quella che C / C ++ non dichiara non definita, lo farà sempre per ottenere il byte alto.
Il problema è quando inizi a leggere i flussi di byte. Come da un file.
I valori a 16 bit presentano gli stessi problemi di quelli a 32 bit; hanno solo 2 byte anziché 4. Pertanto, un file può contenere valori a 16 bit memorizzati in ordine big endian o little endian.
UTF-16 è definito come una sequenza di valori a 16 bit . In effetti, è un uint16_t[]
. Ogni singola unità di codice ha un valore di 16 bit. Pertanto, per caricare correttamente UTF-16, è necessario sapere qual è l'endianità dei dati.
UTF-8 è definito come una sequenza di valori a 8 bit . È un uint8_t[]
. Ogni singola unità di codice ha una dimensione di 8 bit: un singolo byte.
Ora, sia UTF-16 che UTF-8 consentono a più unità di codice (valori di 16 bit o 8 bit) di combinarsi insieme per formare un punto di codice Unicode (un "carattere", ma non è il termine corretto; è una semplificazione ). L' ordine di queste unità di codice che formano un punto di codice è dettato dalle codifiche UTF-16 e UTF-8.
Durante l'elaborazione di UTF-16, leggi un valore a 16 bit, facendo qualunque conversione endian sia necessaria. Quindi, si rileva se si tratta di una coppia surrogata; se lo è, allora leggi un altro valore a 16 bit, combini i due e da quello ottieni il valore del punto di codice Unicode.
Durante l'elaborazione di UTF-8, leggi un valore di 8 bit. Non è possibile alcuna conversione endian, poiché esiste un solo byte. Se il primo byte indica una sequenza multibyte, allora leggi un certo numero di byte, come dettato dalla sequenza multibyte. Ogni singolo byte è un byte e quindi non ha una conversione endian. L' ordine di questi byte nella sequenza, proprio come l'ordine delle coppie surrogate in UTF-16, è definito da UTF-8.
Quindi non ci possono essere problemi di endian con UTF-8.