首页 > 解决方案 > 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++gccvisual-c++unicodeutf-8

解决方案


他们都错了。

据我所知,C++17 标准在这里说:

窄字符串文字的大小是转义序列和其他字符的总数,加上每个通用字符名称的多字节编码至少一个,加上终止 '\0' 的一个。

尽管还有其他提示,但这似乎是转义序列不是多字节并且 MSVC 的行为是错误的最有力的迹象。

有一些票目前被标记为正在调查中:

然而,它在这里也提到了 UTF-8 文字:

如果该值不能用单个 UTF-8 代码单元表示,则程序格式错误。

由于0xA0不是有效的 UTF-8 字符,因此程序不应编译。

注意:

  • 以 开头的 UTF-8 文字u8被定义为狭义。
  • \xA0是一个转义序列
  • \u00A0被认为是通用字符名称而不是转义序列

推荐阅读