(1) Que signifie la séquence d'octets, un arrary de char en C? UTF-16 est-il une séquence d'octets, ou qu'est-ce que c'est alors? (2) Pourquoi une séquence d'octets n'a-t-elle rien à voir avec une longueur variable?
Vous semblez mal comprendre ce que sont les problèmes endiens. Voici un bref résumé.
Un entier 32 bits occupe 4 octets. Maintenant, nous connaissons l'ordre logique de ces octets. Si vous avez un entier 32 bits, vous pouvez en obtenir l'octet élevé avec le code suivant:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
C'est bien beau. Le problème commence par la façon dont divers matériels stockent et récupèrent les entiers de la mémoire.
Dans l'ordre Big Endian, une mémoire de 4 octets que vous lisez en tant qu'entier 32 bits sera lue, le premier octet étant l'octet de poids fort:
[0][1][2][3]
Dans l'ordre Little Endian, une mémoire de 4 octets que vous lisez comme un entier 32 bits sera lue, le premier octet étant l' octet faible :
[3][2][1][0]
Si vous avez un pointeur sur un pointeur sur une valeur 32 bits, vous pouvez le faire:
uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?
Selon C / C ++, le résultat n'est pas défini. Ce pourrait être 0x81. Ou cela pourrait être 0x32. Techniquement, il pourrait renvoyer n'importe quoi, mais pour les systèmes réels, il retournera l'un ou l'autre.
Si vous avez un pointeur sur une adresse mémoire, vous pouvez lire cette adresse en tant que valeur 32 bits, 16 bits ou 8 bits. Sur une grande machine endienne, le pointeur pointe vers l'octet haut; sur une petite machine endienne, le pointeur pointe vers l'octet bas.
Notez qu'il s'agit de lire et d'écrire sur / depuis la mémoire. Cela n'a rien à voir avec le code C / C ++ interne. La première version du code, celle que C / C ++ ne déclare pas non définie, fonctionnera toujours pour obtenir l'octet de poids fort.
Le problème est lorsque vous commencez à lire des flux d'octets. Comme à partir d'un fichier.
Les valeurs 16 bits ont les mêmes problèmes que celles 32 bits; ils n'ont que 2 octets au lieu de 4. Par conséquent, un fichier peut contenir des valeurs 16 bits stockées dans un ordre big endian ou little endian.
UTF-16 est défini comme une séquence de valeurs 16 bits . En fait, c'est un uint16_t[]
. Chaque unité de code individuelle est une valeur de 16 bits. Par conséquent, afin de charger correctement UTF-16, vous devez connaître l'endian-ness des données.
UTF-8 est défini comme une séquence de valeurs à 8 bits . C'est un uint8_t[]
. Chaque unité de code individuelle a une taille de 8 bits: un seul octet.
Maintenant, UTF-16 et UTF-8 permettent à plusieurs unités de code (valeurs 16 bits ou 8 bits) de se combiner pour former un point de code Unicode (un "caractère", mais ce n'est pas le terme correct; c'est une simplification ). L' ordre de ces unités de code qui forment un point de code est dicté par les codages UTF-16 et UTF-8.
Lors du traitement de l'UTF-16, vous lisez une valeur de 16 bits, en faisant la conversion endienne nécessaire. Ensuite, vous détectez s'il s'agit d'une paire de substitution; si c'est le cas, vous lisez une autre valeur de 16 bits, combinez les deux et à partir de cela, vous obtenez la valeur de point de code Unicode.
Lors du traitement UTF-8, vous lisez une valeur de 8 bits. Aucune conversion endienne n'est possible, car il n'y a qu'un seul octet. Si le premier octet indique une séquence multi-octets, vous lisez un certain nombre d'octets, comme dicté par la séquence multi-octets. Chaque octet individuel est un octet et n'a donc pas de conversion endienne. L' ordre de ces octets dans la séquence, tout comme l'ordre des paires de substitution dans UTF-16, est défini par UTF-8.
Il ne peut donc y avoir aucun problème endien avec UTF-8.