Кодировка Unicode для строковых литералов в C ++ 11 - PullRequest
76 голосов
/ 23 июля 2011

После связанного вопроса я хотел бы спросить о новых символьных и строковых литеральных типах в C ++ 11. Кажется, у нас теперь есть четыре вида символов и пять видов строковых литералов. Типы персонажей:

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

И строковые литералы:

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

Вопрос заключается в следующем: свободно ли сочетаются ссылки на символы \x / \u / \U со всеми типами строк? Все ли строковые типы имеют фиксированную ширину, т. Е. Массивы содержат ровно столько элементов, сколько появляется в литерале, либо ссылки \x / \u / \U расширяются в переменное число байтов? Строки Do u"" и u8"" имеют семантику кодирования, например могу ли я сказать char16_t x[] = u"\U0010FFFF", и кодовая точка, отличная от BMP, кодируется в виде последовательности из двух единиц UTF16? И аналогично для u8? В (1) я могу написать одиночные суррогаты с \u? Наконец, знает ли какая-либо из кодировок строковых функций (то есть они распознают символы и могут обнаружить недопустимые последовательности байтов)?

Это немного открытый вопрос, но я хотел бы получить как можно более полную картину о новом UTF-кодировании и возможностях типов нового C ++ 11.

1 Ответ

51 голосов
/ 23 июля 2011

Свободно ли комбинируются ссылки на символы \ x / \ u / \ U со всеми типами строк?

Нет. \x может использоваться во всем, но \u и \U могут использоваться только в строках, которые имеют UTF-кодировку. Однако для любой строки в кодировке UTF можно использовать \u и \U по своему усмотрению.

Все ли строковые типы имеют фиксированную ширину, т. Е. Массивы содержат ровно столько элементов, сколько появляется в литерале, либо ссылки на \ x / \ u / \ U расширяются в переменное число байтов?

Не так, как вы имеете в виду. \x, \u и \U конвертируются на основе строкового кодирования. Количество этих «единиц кода» (с использованием терминов Unicode. A char16_t - это единица кода UTF-16) зависит от кодировки содержащей строки. Литерал u8"\u1024" создаст строку, содержащую 2 char с плюс нулевой терминатор. Литерал u"\u1024" создаст строку, содержащую 1 char16_t плюс нулевой терминатор.

Количество используемых единиц кода основано на кодировке Unicode.

Строки u "" и u8 "" имеют семантику кодирования, например могу ли я сказать char16_t x [] = u "\ U0010FFFF", и кодовая точка, отличная от BMP, будет закодирована в последовательность из двух единиц UTF16?

u"" создает строку в кодировке UTF-16. u8"" создает строку в кодировке UTF-8. Они будут закодированы в соответствии со спецификацией Unicode.

В (1) я могу написать одинокие суррогаты с \ u?

Абсолютно нет. Спецификация прямо запрещает использование суррогатных пар UTF-16 (0xD800-0xDFFF) в качестве кодовых точек для \u или \U.

Наконец, знает ли какая-либо из кодировок строковых функций (то есть они распознают символы и могут обнаружить недопустимые последовательности байтов)?

Абсолютно нет. Что ж, позвольте мне перефразировать это.

std::basic_string не имеет дело с кодировками Unicode. Они, безусловно, могут хранить строки в кодировке UTF. Но они могут думать о них только как о последовательностях char, char16_t или char32_t; они не могут думать о них как о последовательности кодов Unicode, которые кодируются с помощью определенного механизма. basic_string::length() вернет количество кодовых единиц, а не кодовых точек. И очевидно, что строковые функции стандартной библиотеки C совершенно бесполезны

Следует отметить, однако, что «длина» для строки Unicode не означает количество кодовых точек. Некоторые кодовые точки объединяют «символы» (неудачное имя), которые объединяются с предыдущей кодовой точкой. Таким образом, несколько кодовых точек могут отображаться на один визуальный символ.

Iostreams может фактически читать / записывать значения в кодировке Unicode. Для этого вам нужно будет использовать локаль, чтобы указать кодировку и правильно вставить ее в различные места. Это легче сказать, чем сделать, и у меня нет кода, чтобы показать вам, как это сделать.

...