来自Wikipedia:
为了在C ++编译器中增强对Unicode的支持,char类型的定义已被修改为至少为存储UTF-8的8位编码所需的大小。
我想知道这对于编写便携式应用程序究竟意味着什么。写这个
之间有什么区别吗?const char[] str = "Test String";
还是这个?
const char[] str = u8"Test String";
是否有任何理由不在代码中的每个字符串文字中使用后者?
当TestString中有非ASCII字符时会发生什么?
答案 0 :(得分:23)
"Test String"
的编码是实现定义的系统编码(窄编码,可能是多字节编码)。
u8"Test String"
的编码始终为UTF-8。
这些例子并不十分清楚。如果你在字符串中包含了一些Unicode文字(例如\U0010FFFF
),那么你总是得到那些(编码为UTF-8),但它们是否可以用系统编码的字符串表示,如果是的话它们的价值是,是实施定义的。
如果有帮助,想象一下你是在EBCDIC机器上编写源代码。然后,文字“Test String”在源文件本身中始终是EBCDIC编码的,但u8
- 初始化数组包含UTF-8编码值,而第一个数组包含EBCDIC编码值。
答案 1 :(得分:14)
你引用维基百科:
为了在C ++编译器中增强对Unicode的支持,char类型的定义已被修改为至少为存储UTF-8的8位编码所需的大小。
嗯,“出于目的”并非如此。由于C标准中char
所需的范围,CHAR_BIT
始终保证至少为8位,因此char
始终要求≥8。u8
。这是(引用C ++11§17.5.1.5/ 1)“纳入”C ++标准。
如果我猜测这种措辞改变的目的,那就是为那些不知道依赖C标准的读者澄清事情。
关于"tørrfisk"
文字前缀的效果,
会影响可执行文件中字符串的编码,但
很遗憾, 不会影响该类型。
因此,在u8"tørrfisk"
和char const[n]
两种情况下,您都会获得{{1}}。但是在前一个文字中,编码是为编译器选择的任何内容,例如编码器。使用拉丁语1(或Windows ANSI Western),对于字符大小为9,字符为8个字节,对于数组大小为9,而在后一个字面值中,编码保证为UTF-8,其中“ø”将使用2或3个字节(我不记得确切),对于稍大的数组大小。
答案 2 :(得分:6)
编译器为平台选择自然的本机编码。在典型的POSIX系统上,它可能会选择ASCII,这可能取决于环境设置的ASCII范围之外的字符值。在大型机上,它可能会选择EBCDIC。比较从文件或命令行接收的字符串可能最适合本机字符集。处理使用UTF-8显式编码的文件时,最好使用u8"..."
字符串。
也就是说,随着最近与字符编码有关的变化,C和C ++中字符串处理的基本假设被破坏了:每个内部字符对象(char
,wchar_t
等)用于表示一个角色。对于UTF-8字符串来说,这显然不再正确,因为每个字符对象只表示某个字符的字节。因此,所有字符串操作,字符分类等功能都不一定适用于这些字符串。我们没有任何好的图书馆可以处理这些字符串以包含在标准中。
答案 3 :(得分:4)
如果编译器的执行字符集设置为UTF-8,则使用u8
时没有区别,因为编译器会将字符转换为UTF-8在这两种情况下。
但是,如果编译器执行字符集是系统的非UTF8代码页(例如Visual C ++的默认代码页),则省略u8
时可能无法正确处理非ASCII字符。例如,转换为宽字符串会崩溃,例如在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.