c++ - GCC 和 MSVC 中的 C++ utf-8 文字
问题描述
这里我有一些简单的代码:
#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 symbol 中正确编码U+00A0
。
但是在 GCC 的情况下不会发生任何事情。它将字符串视为简单字节。即使我u8
在字符串文字之前删除也没有变化。
C2A0
如果字符串设置为:两个编译器都编码为 utf8 并输出:u8"\u00A0";
为什么编译器的行为不同,实际上哪个是正确的?
用于测试的软件:
海合会 8.3.0
MSVC 19.00.23506
C++ 11
解决方案
他们都错了。
据我所知,C++17 标准在这里说:
窄字符串文字的大小是转义序列和其他字符的总数,加上每个通用字符名称的多字节编码至少一个,加上终止 '\0' 的一个。
尽管还有其他提示,但这似乎是转义序列不是多字节并且 MSVC 的行为是错误的最有力的迹象。
有一些票目前被标记为正在调查中:
- https://developercommunity.visualstudio.com/content/problem/225847/hex-escape-codes-in-a-utf8-literal-are-treatment-in.html
- https://developercommunity.visualstudio.com/content/problem/260684/escape-sequences-in-unicode-string-literals-are-ov.html
然而,它在这里也提到了 UTF-8 文字:
如果该值不能用单个 UTF-8 代码单元表示,则程序格式错误。
由于0xA0
不是有效的 UTF-8 字符,因此程序不应编译。
注意:
- 以 开头的 UTF-8 文字
u8
被定义为狭义。 \xA0
是一个转义序列\u00A0
被认为是通用字符名称而不是转义序列