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
шестнадцатеричный-четверной
\U
шестнадцатеричный шестнадцатеричный
шестнадцатеричный шестнадцатеричный:
шестнадцатеричная цифра шестнадцатеричная цифра шестнадцатеричная цифра шестнадцатеричная цифра
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>
.