C99 або раніше
Стандарт C (C99) передбачає широкі та багатобайтові символи, але оскільки немає гарантії щодо вмісту цих широких символів, їх значення дещо обмежене. Для даної реалізації вони надають корисну підтримку, але якщо ваш код повинен мати можливість переходити між реалізаціями, недостатньо гарантій, що вони будуть корисними.
Отже, підхід, запропонований Гансом ван Екком (який полягає у написанні обгортки навколо ICU - International Components for Unicode - бібліотеки), є вигідним, IMO.
Кодування UTF-8 має багато достоїнств, одне з яких полягає в тому, що якщо ви не возитиметеся з даними (наприклад, скорочуючи їх), його можна скопіювати функціями, які не до кінця усвідомлюють тонкощі UTF-8 кодування. Це категорично не такwchar_t
.
Unicode в повному обсязі - це 21-розрядний формат. Тобто Unicode резервує кодові точки від U + 0000 до U + 10FFFF.
Однією з корисних речей щодо форматів UTF-8, UTF-16 та UTF-32 (де UTF розшифровується як Формат перетворення Unicode - див. Unicode ) є те, що ви можете перетворювати між трьома поданнями без втрати інформації. Кожен може представляти все, що можуть представляти інші. І UTF-8, і UTF-16 є багатобайтовими форматами.
Загальновідомо, що UTF-8 є багатобайтовим форматом, з ретельною структурою, яка дозволяє надійно знаходити початок символів у рядку, починаючи з будь-якої точки рядка. Однобайтові символи мають високий біт, встановлений на нуль. Багатобайтові символи мають перший символ, що починається з одного з бітових шаблонів 110, 1110 або 11110 (для 2-байтових, 3-байтових або 4-байтових символів), а наступні байти завжди починаються 10. Символи продовження завжди знаходяться в діапазон 0x80 .. 0xBF. Існують правила, згідно з якими символи UTF-8 повинні бути представлені у мінімально можливому форматі. Одним із наслідків цих правил є те, що байти 0xC0 та 0xC1 (також 0xF5..0xFF) не можуть відображатися у дійсних даних UTF-8.
U+0000 .. U+007F 1 byte 0xxx xxxx
U+0080 .. U+07FF 2 bytes 110x xxxx 10xx xxxx
U+0800 .. U+FFFF 3 bytes 1110 xxxx 10xx xxxx 10xx xxxx
U+10000 .. U+10FFFF 4 bytes 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
Спочатку сподівалися, що Unicode буде 16-розрядним набором коду, і все вміститься в 16-розрядний простір коду. На жаль, реальний світ складніший, і його довелося розширити до поточного 21-бітового кодування.
Таким чином, UTF-16 є єдиним одиничним (16-бітовим словом) кодом для "Базової багатомовної площини", тобто символами з кодовими точками Unicode U + 0000 .. U + FFFF, але використовує дві одиниці (32 біти) для символів поза цим діапазоном. Таким чином, код, який працює з кодуванням UTF-16, повинен мати можливість обробляти кодування змінної ширини, як і UTF-8. Коди символів із подвійними одиницями називаються сурогатами.
Сурогати - це кодові точки з двох спеціальних діапазонів значень Unicode, зарезервованих для використання в якості провідних, і кінцевих значень спарених одиниць коду в UTF-16. Провідні, які також називають високими, сурогати - від U + D800 до U + DBFF, а кінцеві, або низькі, сурогати - від U + DC00 до U + DFFF. Їх називають сурогатами, оскільки вони не представляють персонажів безпосередньо, а лише у вигляді пари.
UTF-32, звичайно, може кодувати будь-яку точку коду Unicode в одній одиниці пам'яті. Це ефективно для обчислень, але не для зберігання.
Ви можете знайти набагато більше інформації на веб-сайтах ICU та Unicode.
C11 та <uchar.h>
Стандарт C11 змінив правила, але не всі реалізації наздогнали зміни навіть зараз (середина 2017 року). Стандарт C11 узагальнює зміни щодо підтримки Unicode як:
- Символи та рядки Unicode (
<uchar.h>
) (спочатку зазначено у ISO / IEC TR 19769: 2004)
Далі йде лише мінімальна схема функціональності. Специфікація включає:
6.4.3 Універсальні імена символів
Синтаксис
універсальний-ім'я-ім'я:
\u
hex-quad
\U
hex-quad hex-quad
hex-quad:
hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit
7.28 Утиліти Unicode <uchar.h>
Заголовок <uchar.h>
оголошує типи та функції для маніпулювання символами Unicode.
mbstate_t
Заявлені типи (описані в 7.29.1) та size_t
(описані в 7.19);
char16_t
це цілий беззнаковий тип, що використовується для 16-бітових символів, і є тим самим типом, що і uint_least16_t
(описаний у 7.20.1.2); і
char32_t
це цілий беззнаковий тип, що використовується для 32-розрядних символів, і є тим самим типом, що і uint_least32_t
(також описаний у 7.20.1.2).
(Переклад перехресних посилань: <stddef.h>
визначає size_t
,
<wchar.h>
визначає mbstate_t
та <stdint.h>
визначає uint_least16_t
та uint_least32_t
.) <uchar.h>
Заголовок також визначає мінімальний набір (перезавантажуваних) функцій перетворення:
mbrtoc16()
c16rtomb()
mbrtoc32()
c32rtomb()
Існують правила щодо того, які символи Unicode можна використовувати в ідентифікаторах, використовуючи позначення \unnnn
або \U00nnnnnn
. Можливо, вам доведеться активно активувати підтримку таких символів в ідентифікаторах. Наприклад, GCC вимагає -fextended-identifiers
дозволити їх в ідентифікаторах.
Зверніть увагу, що macOS Sierra (10.12.5), якщо назвати лише одну платформу, не підтримує <uchar.h>
.