В шаблоне \U
есть более длинная форма escape, за которой следуют восемь цифр, а не \u
, за которой следуют четыре цифры. Это также используется в Java и Python, среди прочего:
>>> '\xf0\x90\x84\x82'.decode("UTF-8")
u'\U00010102'
Однако, если вы используете строки байтов, почему бы просто не экранировать каждый байт, как указано выше, вместо того, чтобы полагаться на компилятор для преобразования экранирования в строку UTF-8? Это также может показаться более переносимым - если я скомпилирую следующую программу:
#include <iostream>
#include <string>
int main()
{
std::cout << "narrow: " << std::string("\uFF0E").length() <<
" utf8: " << std::string("\xEF\xBC\x8E").length() <<
" wide: " << std::wstring(L"\uFF0E").length() << std::endl;
std::cout << "narrow: " << std::string("\U00010102").length() <<
" utf8: " << std::string("\xF0\x90\x84\x82").length() <<
" wide: " << std::wstring(L"\U00010102").length() << std::endl;
}
На win32 с моими текущими настройками cl дает:
warning C4566: character represented by universal-character-name '\UD800DD02' cannot be represented in the current code page (932)
Компилятор пытается преобразовать все экранированные символы Юникода в байтовых строках в системную кодовую страницу, которая в отличие от UTF-8 не может представлять все символы Юникода. Как ни странно, он понял, что \U00010102
равен \uD800\uDD02
в UTF-16 (его внутреннее представление в кодировке Unicode), и исказил escape в сообщении об ошибке ...
При запуске программа печатает:
narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2
Обратите внимание, что строки байтов UTF-8 и широкие строки верны, но компилятору не удалось преобразовать "\U00010102"
, что дает строку байтов "??"
, неверный результат.