首页 > 解决方案 > 为什么 '€' == '\€' 但 "€" != "\€" 和 u8"€" != u8"\€"

问题描述

在到处阅读 utf8 之后,我试图更改我的一些代码以使用 std::string。我假设如果我将 std::string 设置为 u8"€" (这是我键盘上的欧元符号 AltGr+4),std::string 将有 3 个字节包含欧元符号的 unicode 代码 (\U20AC)。它没有。考虑

std::string x[] = {"€", u8"€", u8"\€", "\u20AC", u8"\u20AC"}

size_t size[] = {x[0].size(), x[1].size(), x[2].size(), x[3].size(), x[4].size()};

如果我在调试器局部变量中查看结果,我会看到

x[] = {"€", "€", "â??", "€", "€"}

size[] = {1, 1, 3, 3, 3}

从我所看到的最后两个是唯一给我预期结果的。我显然错过了与字符串文字有关的东西,但我也很困惑调试器如何为前两个显示正确的字符串,因为它认为它们是一个字符长并且(int64_t(x[0].c_str()[0]) == int64_t(x[1].c_str()[0]) == -128.

还有为什么 '€' == '\€' 但是 "€" != "\€" 和 u8"€" != u8"\€"。(编辑:忽略这个。Remy 在下面指出我的错误重新比较 char指针)。

结果还提出了一个问题 u8 字符串文字前缀的目的是什么?

在我恢复到 wchar_t 之前,有人可以解释一下吗?

我在使用 RAD studio 10.2 的 Windows 10 上。

编辑:使用字符映射工具对各种非 ASCII Unicode 字符进行了尝试。无法让它与他们中的任何一个一起工作。size() 始终为 1,并且调试器显示与我使用的字符不同的字符(通常是“?”)。我使用的是 Surface Pro 类型的封面,据我所知,无法使用键盘输入随机的 Unicode 字符(除了 €)。从现在开始为我严格反斜杠代码。很高兴我已经把它清理干净了,即使我浪费了一整天。谢谢大家。

标签: c++string-literals

解决方案


我假设如果我将 std::string 设置为 u8"€" (这是我键盘上的欧元符号 AltGr+4),std::string 将有 3 个字节包含欧元符号的 unicode 代码 (\U20AC)。它没有。

它应该,是的。前缀保证文字在u8最终可执行文件中存储为 UTF-8,并且 U+20AC 在 UTF-8 中确实编码为 3 个字节。如果您看到不同的东西,那很可能是应该报告给 Embarcadero 的编译器错误。

我也很困惑调试器如何为前两个显示正确的字符串,因为它认为它们是一个字符长并且(int64_t(x[0].c_str()[0]) == int64_t(x[1].c_str()[0]) == -128.

第二个应该是 3 个字节,而不是 1 个字节。

由于两者都是 1 字节,显示只是偶然的。字符串文字没有前缀,因此使用编译器的默认 ANSI 字符集进行解释,在您的情况下,它必须恰好在字节 0x80 处具有欧元符号。

还有为什么 '€' == '\€' 但 "€" != "\€" 和 u8"€" != u8"\€"。

因为第一个是比较实际char值,而另一个是比较原始char*指针,而不是实际char值。

结果还提出了一个问题 u8 字符串文字前缀的目的是什么?

正是您所期望的 - 它应该使编译器以 UTF-8 编码输出字符串文字的内容。


推荐阅读