在C ++ 11中是否需要u8字符串文字

时间:2012-11-18 21:42:26

标签: c++ utf-8 c++11 literals string-literals

来自Wikipedia

  

为了在C ++编译器中增强对Unicode的支持,char类型的定义已被修改为至少为存储UTF-8的8位编码所需的大小。

我想知道这对于编写便携式应用程序究竟意味着什么。写这个

之间有什么区别吗?
const char[] str = "Test String";

还是这个?

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

是否有任何理由不在代码中的每个字符串文字中使用后者?

当TestString中有非ASCII字符时会发生什么?

4 个答案:

答案 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 ++中字符串处理的基本假设被破坏了:每个内部字符对象(charwchar_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.