(1) Що означає послідовність байтів, довільна таблиця знаків у С? Чи є UTF-16 послідовністю байтів, або що це тоді? (2) Чому послідовність байтів не має нічого спільного зі змінною довжиною?
Ви, здається, нерозумієте, що таке ендіанські проблеми Ось короткий підсумок.
32-бітове ціле число займає 4 байти. Тепер ми знаємо логічне впорядкування цих байтів. Якщо у вас є 32-бітове ціле число, ви можете отримати високий байт цього коду за допомогою наступного коду:
uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81
Це все добре і добре. Звідки починається проблема - це те, як різні апаратури зберігають і витягують цілі числа з пам'яті.
У порядку Big Endian 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-бітних значень . Це a 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 не може бути ніяких проблем.