(1) Что означает последовательность байтов, набор символов в C? Является ли UTF-16 байтовой последовательностью или что это тогда? (2) Почему последовательность байтов не имеет ничего общего с переменной длиной?
Похоже, вы неправильно понимаете, что такое порядковый номер. Вот краткое резюме.
32-разрядное целое число занимает 4 байта. Теперь мы знаем логический порядок этих байтов. Если у вас есть 32-разрядное целое число, вы можете получить старший байт этого с помощью следующего кода:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
Это все хорошо. Проблема начинается с того, как различное оборудование хранит и извлекает целые числа из памяти.
В порядке с прямым порядком байтов 4-байтовый фрагмент памяти, который вы читаете как 32-разрядное целое число, будет прочитан, причем первый байт будет старшим байтом:
[0][1][2][3]
В порядке Little Endian 4-байтовый фрагмент памяти, который вы читаете как 32-разрядное целое число, будет читаться с первым байтом, являющимся младшим байтом:
[3][2][1][0]
Если у вас есть указатель на указатель на 32-битное значение, вы можете сделать это:
uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?
Согласно C / C ++, результат этого не определен. Это может быть 0x81. Или это может быть 0x32. Технически, он может вернуть все что угодно, но для реальных систем он вернет одну или другую.
Если у вас есть указатель на адрес памяти, вы можете прочитать этот адрес как 32-разрядное значение, 16-разрядное значение или 8-разрядное значение. На старшей байтовой машине указатель указывает на старший байт; на машине с прямым порядком байтов указатель указывает на младший байт.
Обратите внимание, что это все о чтении и записи в / из памяти. Это не имеет ничего общего с внутренним кодом C / C ++. Первая версия кода, которую C / C ++ не объявляет как неопределенную, всегда будет работать для получения старшего байта.
Проблема в том, когда вы начинаете читать потоки байтов. Например, из файла.
16-битные значения имеют те же проблемы, что и 32-битные; у них просто 2 байта вместо 4. Следовательно, файл может содержать 16-битные значения, хранящиеся в порядке с прямым или прямым порядком байтов.
UTF-16 определяется как последовательность 16-битных значений . По сути, это uint16_t[]
. Каждая единица кода является 16-битным значением. Следовательно, для правильной загрузки UTF-16 вы должны знать, что такое порядок данных.
UTF-8 определяется как последовательность 8-битных значений . Это uint8_t[]
. Каждая единица кода имеет размер 8 битов: один байт.
Теперь, как UTF-16 и UTF-8 позволяют несколько блоков кода (16-битные или 8-разрядные значения) , чтобы объединить вместе , чтобы сформировать элемент кода Unicode (а «символ», но это не правильный термин, это упрощение ). Порядок этих кодовых блоков , которые образуют элемент кода диктуется UTF-16 и UTF-8 кодировке.
При обработке UTF-16 вы читаете 16-битное значение, выполняя любое обратное преобразование. Затем вы обнаруживаете, если это суррогатная пара; если это так, тогда вы читаете еще одно 16-битное значение, объединяете их, и из этого вы получаете значение кодовой точки Unicode.
При обработке UTF-8 вы читаете 8-битное значение. Преобразование в обратный порядок не возможно, поскольку существует только один байт. Если первый байт обозначает многобайтовую последовательность, то вы читаете некоторое количество байтов, как предписано многобайтовой последовательностью. Каждый отдельный байт является байтом и, следовательно, не имеет порядка байтов. Порядок этих байтов в последовательности, так же , как порядок суррогатных пар в UTF-16, определяется UTF-8.
Таким образом, с UTF-8 не может быть проблем с порядком байтов.