【发布时间】:2020-08-13 18:46:05
【问题描述】:
这里有一些简单的代码:
#include <iostream>
#include <cstdint>
int main()
{
const unsigned char utf8_string[] = u8"\xA0";
std::cout << std::hex << "Size: " << sizeof(utf8_string) << std::endl;
for (int i=0; i < sizeof(utf8_string); i++) {
std::cout << std::hex << (uint16_t)utf8_string[i] << std::endl;
}
}
我在这里看到 MSVC 和 GCC 的不同行为。
MSVC 将"\xA0" 视为未编码的 unicode 序列,并将其编码为 utf-8。
所以在 MSVC 中的输出是:
C2A0
在 utf8 unicode 符号 U+00A0 中正确编码。
但在 GCC 的情况下不会发生任何事情。它将字符串视为简单字节。即使我在字符串文字之前删除 u8 也没有任何变化。
如果字符串设置为:u8"\u00A0";,则两个编译器都编码为 utf8 并输出 C2A0:u8"\u00A0";
为什么编译器的行为会有所不同,哪些实际上是正确的?
用于测试的软件:
GCC 8.3.0
MSVC 19.00.23506
C++ 11
【问题讨论】:
-
你在 MSVC 上得到了什么输出(PS:我没有)?在
g++和clang我得到这个:Size: 2 a0 0。 -
u8的输出是标准的,必须是UTF-8。但是对u8的输入 的解释可能不是标准的。\uXXXX和\UXXXXXXXX的行为是标准的,它们必须被解释为代码点。但是\xXX的解释更多是由实现定义的。\xA0可以按原样解释为单个char0xA0,也可以扩展为代码点 U+00A0,然后编码为 2chars0xC2 0xA0。您会看到这两种行为。 -
@RemyLebeau 你能为“
\xA0可能(..)扩展为代码点”提供一些参考吗,因为en.cppreference.com/w/cpp/language/escape 说\xnn是一个字节而不是一个代码点。 -
@MrLister cppreference.com 通常是可靠的,但并非绝对可靠。鉴于 UTF-8 具有成为有效字节序列的规则,因此编译器可以在必要时应用一些翻译并不是不合理的。
-
character literal
U8'\xA0'格式不正确(因为代码点不能用单个 UTF-8 代码单元表示),所以我希望一个带有这种文字的字符串会也会导致程序格式错误。
标签: c++ gcc visual-c++ unicode utf-8