C99 или ранее
Стандарт C (C99) предусматривает широкие символы и многобайтовые символы, но, поскольку нет гарантии, что эти широкие символы могут содержать, их значение несколько ограничено. Для данной реализации они предоставляют полезную поддержку, но если ваш код должен иметь возможность перемещаться между реализациями, нет достаточной гарантии, что они будут полезны.
Следовательно, подход, предложенный Хансом ван Экком (который должен написать обертку вокруг ICU - International Components for Unicode - library), является здравым, IMO.
Кодировка UTF-8 имеет много достоинств, одним из которых является то, что если вы не будете связываться с данными (например, обрезая их), то они могут быть скопированы функциями, которые не в полной мере осведомлены о тонкостях Кодировка UTF-8. Это категорически не так с wchar_t
.
Юникод в полном объеме - это 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
hex-quad hex-quad
шестигранной четырехъядерный:
шестнадцатеричная цифра шестнадцатеричная цифра
шестнадцатеричная цифра шестнадцатеричная цифра
7.28 Утилиты Unicode <uchar.h>
Заголовок <uchar.h>
объявляет типы и функции для работы с символами Юникода.
Заявленные типы: 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>
.