UNICODE usa 2 bytes para um caractere, então tem grande ou pequena diferença endian. Por exemplo, o caractere 哈 está 54 C8
em hexadecimal. E seu UTF-8, portanto, é:
11100101 10010011 10001000
O UTF-8 usa 3 bytes para apresentar o mesmo caractere, mas não possui big ou little endian. Por quê?
Nota: O Windows usa o termo "Unicode" para UCS-2 devido a razões históricas - originalmente, essa era a única maneira de codificar pontos de código Unicode em bytes, portanto, a distinção não importava. Mas na terminologia moderna, ambos os exemplos são Unicode, mas o primeiro é especificamente UCS-2 ou UTF-16 e o segundo é UTF-8.
O UCS-2 tinha big-endian e little-endian porque representava diretamente o codepoint como um número 'uint16_t' ou 'short int' de 16 bits, como em C e outras linguagens de programação. Não é tanto uma 'codificação' como uma representação direta de memória dos valores numéricos, e como um uint16_t pode ser BE ou LE em máquinas diferentes, o mesmo acontece com o UCS-2. O UTF-16 posterior apenas herdou a mesma bagunça para compatibilidade.
(Provavelmente poderia ter sido definido para um endian específico, mas acho que eles sentiram que estava fora do escopo ou teve que se comprometer entre pessoas que representam diferentes fabricantes de hardware ou algo assim. Não conheço a história real.)
Enquanto isso, UTF-8 é uma codificação de comprimento variável, que pode usar de 1 a 6 bytes para representar um valor de 31 bits. A representação de byte não tem nenhuma relação com a arquitetura da CPU; em vez disso , existe um algoritmo específico para codificar um número em bytes e vice-versa. O algoritmo sempre emite ou consome bits na mesma ordem, não importa em qual CPU ele esteja sendo executado.
Exatamente a mesma razão pela qual uma matriz de bytes (
char[]
em C oubyte[]
em muitas outras linguagens) não possui nenhuma endianidade associada, mas matrizes de outros tipos maiores quebyte
. É porque endianness é a maneira como você armazena um valor representado por vários bytes na memória . Se você tiver apenas um único byte, terá apenas 1 maneira de armazená-lo na memória. Mas se umint
for composto por 4 bytes com índice de 1 a 4, você poderá armazená-lo em várias ordens diferentes, como [1, 2, 3, 4], [4, 3, 2, 1], [2, 1, 4, 3], [3, 1, 2, 4]... que é little endian, big endian, mixed endian...O Unicode tem muitas codificações diferentes chamadas Unicode Transformation Format , sendo as principais UTF-8, UTF-16 e UTF-32. UTF-16 e UTF-32 trabalham em uma unidade de 16 e 32 bits respectivamente, e obviamente quando você armazena 2 ou 4 bytes na memória endereçada a byte você deve definir uma ordem dos bytes para leitura/gravação. UTF-8 OTOH funciona em uma unidade de byte , portanto, não há endianness nela
A razão (ou explicação potencial) é que esses três bytes estão codificando os bits de ponto de código diferente do UTF-16:
Os 16 bits do ponto de código (
01010100 11001000
[哈54 C8
]) são distribuídos em três bytes no fluxo de bytes UTF-8 (um primeiro e dois bytes de continuação).Pelas regras da codificação, o bit mais significativo é sempre o mais à esquerda. Isso permite analisar UTF-8 byte por byte do índice de byte mais baixo para o mais alto.
Compare: UTF-8 (formulário de codificação D92 UTF-8 - Formulários de codificação Unicode 3.9, Unicode 14.0.0 p. 123)
Como o número do ponto de código é armazenado na memória do computador não é afetado por isso.
Com UTF-16 não é tão claro, pois UTF-16 pode sugerir ler o fluxo de bytes palavra por palavra (não byte por byte). Doravante, o significado da ordem dos bytes dentro de uma palavra (e, portanto, também a ordem dos bits) pode variar:
Se você agora mapear palavras do fluxo para a memória do computador, precisará fazer uma correspondência para a arquitetura para obter o valor do ponto de código.
Veja também: Diferença entre a ordem Big Endian e Little Endian Byte
Aqui está o material oficial de fonte primária (publicado em março de 2020):
"The Unicode® Standard, Versão 13.0"
Capítulo 2: Estrutura geral (página 39 do documento; página 32 do PDF)
Consulte também as seguintes informações relacionadas:
O motivo é muito simples. Existem versões big e little endian de UTF-16 e UTF-32 porque existem computadores com registradores bit e little endian. Se a endianness de um arquivo Unicode corresponder à endianness do processador, o valor do caractere poderá ser lido diretamente da memória em uma única operação. Se eles não corresponderem, uma segunda etapa de conversão será necessária para inverter o valor.
Em contraste, o endianness do processador é irrelevante ao ler UTF-8. O programa deve ler os bytes individuais e realizar uma série de testes e deslocamentos de bits para obter o valor do caractere em um registrador. Ter uma versão em que a ordem dos bytes fosse invertida seria inútil.
De acordo com alguma documentação do Windows, a codificação mapeia para um fluxo de até 4 bytes. Também se diz que não importa a endianness do processador. Então, o que eu acho que isso significa para o desenvolvedor é que você não deve se preocupar com endianess com utf-8 no Windows. Essa é a filosofia do projeto. Portanto, agora você deve se concentrar em quão apropriadamente você deve usar a funcionalidade do Windows para que isso não importe. Agora, os fluxos que chegam seriam importantes, mas a decodificação e a codificação de utf-8 você não deve ter que lidar.
No entanto, é possível ir por baixo disso, para entender completamente, o que pode ajudar. Mas basicamente o Windows diz que você não precisa conhecer a endianess do sistema para lidar com utf-8 para codificar e decodificar fluxos para utf-8.