От Википедия:
В целях расширения поддержки Unicode в компиляторах C ++ определение типа char было изменено так, чтобы оно соответствовало по крайней мере размеру, необходимому для хранения восьмибитной кодировки UTF-8.
Мне интересно, что именно это означает для написания портативных приложений. Есть ли разница между написанием этого
const char[] str = "Test String";
или это?
const char[] str = u8"Test String";
Есть ли какая-либо причина не использовать последний для каждого строкового литерала в вашем коде?
Что происходит, когда в TestString есть не-ASCII-символы?
Кодировка "Test String"
является определяемой реализацией системной кодировкой (узкая, возможно многобайтовая).
Кодировка u8"Test String"
всегда UTF-8.
Примеры не очень страшны. Если вы включили некоторые литералы Unicode (такие как \U0010FFFF
) в строку, то вы всегда получите их (закодированные как UTF-8), но могут ли они быть выражены в системно-закодированной строке, и если да, каково их значение, определяется реализацией.
Если это поможет, представьте, что вы создаете исходный код на машине EBCDIC. Тогда литерал «Test String» всегда кодируется в EBCDIC в самом исходном файле, но u8
-инициализированный массив содержит значения в кодировке UTF-8, тогда как первый массив содержит значения в кодировке EBCDIC.
Вы цитируете Википедию:
В целях расширения поддержки 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 байта (точно не помню), для немного большего размера массива.
Компилятор выбирает естественную кодировку, естественную для платформы. В типичных системах POSIX он, вероятно, выберет ASCII и что-то, возможно, в зависимости от настроек среды для символьных значений вне диапазона ASCII. На мэйнфреймах он, вероятно, выберет EBCDIC. Сравнение строк, полученных, например, из файлов или командной строки, вероятно, будет лучше всего работать с собственным набором символов. Однако при обработке файлов, явно закодированных с использованием UTF-8, лучше всего использовать u8"..."
строки.
Тем не менее, с недавними изменениями, касающимися кодировки символов, фундаментальное предположение об обработке строк в C и C ++ было нарушено: каждый внутренний символьный объект (char
, wchar_t
и т. д.) используется для обозначения одного символа. Это явно не соответствует действительности для строки UTF-8, где каждый символьный объект представляет собой байт некоторого символа. В результате все функции обработки строк, классификации символов и т. Д. Не обязательно будут работать с этими строками. У нас нет хорошей библиотеки для работы с такими строками для включения в стандарт.
Если набор символов исполнения компилятора установлен в 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.