Нужен ли строковый литерал u8 в C ++ 11?

От Википедия:

В целях расширения поддержки Unicode в компиляторах C ++ определение типа char было изменено так, чтобы оно соответствовало по крайней мере размеру, необходимому для хранения восьмибитной кодировки UTF-8.

Мне интересно, что именно это означает для написания портативных приложений. Есть ли разница между написанием этого

const char[] str = "Test String";

или это?

const char[] str = u8"Test String";

Есть ли какая-либо причина не использовать последний для каждого строкового литерала в вашем коде?

Что происходит, когда в TestString есть не-ASCII-символы?

19

Решение

Кодировка "Test String" является определяемой реализацией системной кодировкой (узкая, возможно многобайтовая).

Кодировка u8"Test String" всегда UTF-8.

Примеры не очень страшны. Если вы включили некоторые литералы Unicode (такие как \U0010FFFF) в строку, то вы всегда получите их (закодированные как UTF-8), но могут ли они быть выражены в системно-закодированной строке, и если да, каково их значение, определяется реализацией.

Если это поможет, представьте, что вы создаете исходный код на машине EBCDIC. Тогда литерал «Test String» всегда кодируется в EBCDIC в самом исходном файле, но u8-инициализированный массив содержит значения в кодировке UTF-8, тогда как первый массив содержит значения в кодировке EBCDIC.

20

Другие решения

Вы цитируете Википедию:

В целях расширения поддержки Unicode в компиляторах C ++ определение типа char было изменено так, чтобы оно соответствовало по крайней мере размеру, необходимому для хранения восьмибитной кодировки UTF-8.

Ну, «для цели» это фигня. char всегда гарантированно было по крайней мере 8 бит, то есть CHAR_BIT всегда требовалось быть ≥8, из-за диапазона, необходимого для char в стандарте C. Что (цитата C ++ 11 §17.5.1.5 / 1) «включено» в стандарт C ++.

Если бы я догадался о цель об этом изменении формулировки было бы просто прояснить вещи для тех читателей, которые не знают о зависимости от стандарта C.

Относительно эффекта u8 буквальный префикс, это

  • влияет на кодировку строки в исполняемом файле, но

  • к сожалению это не влияет на тип.

Таким образом, в обоих случаях "tørrfisk" а также u8"tørrfisk" Вы получаете char const[n], Но в первом литерале кодировка — это то, что выбрано для компилятора, например с латинским 1 (или Windows ANSI Western) это будет 8 байтов для символов плюс нульбайт для размера массива 9. В то время как в последнем литерале кодировка гарантированно будет UTF-8, где «ø» будет кодироваться с помощью 2 или 3 байта (точно не помню), для немного большего размера массива.

12

Компилятор выбирает естественную кодировку, естественную для платформы. В типичных системах POSIX он, вероятно, выберет ASCII и что-то, возможно, в зависимости от настроек среды для символьных значений вне диапазона ASCII. На мэйнфреймах он, вероятно, выберет EBCDIC. Сравнение строк, полученных, например, из файлов или командной строки, вероятно, будет лучше всего работать с собственным набором символов. Однако при обработке файлов, явно закодированных с использованием UTF-8, лучше всего использовать u8"..." строки.

Тем не менее, с недавними изменениями, касающимися кодировки символов, фундаментальное предположение об обработке строк в C и C ++ было нарушено: каждый внутренний символьный объект (char, wchar_tи т. д.) используется для обозначения одного символа. Это явно не соответствует действительности для строки UTF-8, где каждый символьный объект представляет собой байт некоторого символа. В результате все функции обработки строк, классификации символов и т. Д. Не обязательно будут работать с этими строками. У нас нет хорошей библиотеки для работы с такими строками для включения в стандарт.

4

Если набор символов исполнения компилятора установлен в UTF-8, это не имеет значения, если u8 используется или нет, так как компилятор преобразует символы в UTF-8 в обоих случаях.

Однако если набор символов выполнения компилятора является системной кодовой страницей, отличной от UTF8 (по умолчанию, например, Visual C ++), то символы, не входящие в ASCII, могут обрабатываться неправильно, когда u8 опущен Например, произойдет сбой преобразования в широкие строки, например, в VS15:

std::string narrowJapanese("スタークラフト");
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convertWindows;
std::wstring wide = convertWindows.from_bytes(narrowJapanese); // Unhandled C++ exception in xlocbuf.
2
По вопросам рекламы [email protected]