Подтвердить что ты не робот

Char vs wchar_t vs char16_t vs char32_t (С++ 11)

Из того, что я понимаю, char безопасен для размещения символов ASCII, тогда как char16_t и char32_t безопасны для размещения символов из Юникода, один для 16-битного сорта, а другой для 32-битного сорта ( Должен ли я сказать "a" вместо "the"?). Но меня тогда интересует, какова цель, стоящая за wchar_t. Должен ли я когда-либо использовать этот тип в новом коде, или он просто поддерживает старый код? Какова была цель wchar_t в старом коде, если из того, что я понимаю, его размер не имел гарантии быть больше, чем char? Уточнение будет приятным!

4b9b3361

Ответ 1

char предназначен для 8-разрядных кодовых блоков, char16_t предназначен для 16-разрядных кодовых блоков, а char32_t - для 32-разрядных кодовых блоков. Любой из них может использоваться для "Unicode"; UTF-8 использует 8-битные кодовые единицы, UTF-16 использует 16-битные кодовые единицы, а UTF-32 использует 32-битные кодовые единицы.


Гарантия на wchar_t заключалась в том, что любой символ, поддерживаемый в локали, может быть преобразован из char в wchar_t, и любое представление, используемое для char, будь то несколько байтов, коды сдвига, что вы, wchar_t будет единственным, отличным значением. Целью этого было то, что тогда вы могли бы манипулировать строками wchar_t так же, как простые алгоритмы, используемые с ASCII.

Например, преобразование ascii в верхний регистр выглядит следующим образом:

auto loc = std::locale("");

char s[] = "hello";
for (char &c : s) {
  c = toupper(c, loc);
}

Но это не будет обрабатывать преобразование всех символов в UTF-8 в верхний регистр или все символы в другой кодировке, например Shift-JIS. Люди хотели иметь возможность интернационализировать этот код следующим образом:

auto loc = std::locale("");

wchar_t s[] = L"hello";
for (wchar_t &c : s) {
  c = toupper(c, loc);
}

Таким образом, каждый wchar_t является "символом", и если он имеет версию в верхнем регистре, он может быть напрямую преобразован. К сожалению, это не работает все время; Например, на некоторых языках существуют такие странности, как немецкая буква ß, где верхняя версия на самом деле представляет собой два символа SS вместо одного символа.

Таким образом, интернационализированная обработка текста по своей сути сложнее, чем ASCII, и не может быть действительно упрощена в том, как предназначены дизайнеры wchar_t. Как таковые wchar_t и широкие символы вообще не имеют большого значения.

Единственная причина для их использования заключается в том, что они были испечены в некоторых API и платформах. Тем не менее, я предпочитаю придерживаться UTF-8 в своем собственном коде даже при разработке на таких платформах и просто конвертировать на границах API любую кодировку.

Ответ 2

Тип wchar_t был помещен в стандарт, когда Unicode обещал создать 16-битное представление. Большинство поставщиков предпочитают делать wchar_t 32 бита, но один крупный поставщик решил сделать это 16 бит. Поскольку Unicode использует более 16 бит (например, 20 бит), было сочтено, что у нас должны быть лучшие типы символов.

Цель char16_t - представлять UTF16 и char32_t предназначена для непосредственного представления символов Unicode. Тем не менее, в системах, использующих wchar_t как часть их основного интерфейса, вы будете придерживаться wchar_t. Если вы не ограничены, я лично использовал бы char для представления Unicode с использованием UTF8. Проблема с char16_t и char32_t заключается в том, что они не полностью поддерживаются, даже в стандартной библиотеке С++: например, нет потоков, поддерживающих эти типы напрямую, и это больше работает, чем просто создание экземпляра потока для этих типов.