来自维基百科:
为了增强 C++ 编译器中对 Unicode 的支持,已将 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 机器上创作源代码。然后文字“测试字符串”总是在源文件本身中进行 EBCDIC 编码,但u8-initialized 数组包含 UTF-8 编码值,而第一个数组包含 EBCDIC 编码值。
你引用维基百科:
为了在 C++ 编译器中增强对 Unicode 的支持,已将 char 类型的定义修改为至少存储 UTF-8 的八位编码所需的大小。
好吧,“为了目的”是不正确的。由于C 标准中要求的范围char,始终保证至少为 8 位,即CHAR_BIT始终要求≥8 。char这是(引用 C++11 §17.5.1.5/1)“合并”到 C++ 标准中。
如果我应该猜测措辞更改的目的,那将只是为那些不知道对 C 标准的依赖的读者澄清一些事情。
关于u8字面前缀的效果,它
影响可执行文件中字符串的编码,但
不幸的是,它不会影响类型。
因此,在这两种情况下"tørrfisk",u8"tørrfisk"您都会得到一个. 但是在前一种文字中,编码是为编译器选择的任何内容,例如,对于拉丁语 1(或 Windows ANSI Western),对于数组大小为 9,字符为 8 个字节加上一个空字节。而在后一种文字中,编码是保证为 UTF-8,其中“ø”将被编码为 2 或 3 个字节(我不记得确切),用于稍大的数组大小。char const[n]
如果编译器的执行字符集设置为 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.
编译器选择平台自然的本机编码。在典型的 POSIX 系统上,它可能会选择 ASCII 并且可能取决于环境对 ASCII 范围之外的字符值的设置。在大型机上,它可能会选择 EBCDIC。比较从文件或命令行接收的字符串可能最适合使用本机字符集。但是,在处理使用 UTF-8 显式编码的文件时,最好使用u8"..."字符串。
也就是说,随着最近与字符编码相关的变化,C 和 C++ 中字符串处理的基本假设被打破:每个内部字符对象(char、wchar_t等)用于表示一个字符。对于每个字符对象仅代表某个字符的一个字节的 UTF-8 字符串,这显然不再适用。因此,所有字符串操作、字符分类等功能不一定适用于这些字符串。我们没有任何好的库来处理这些字符串以包含在标准中。