C++ C++;:Unicode字符串文本的可移植性

C++ C++;:Unicode字符串文本的可移植性,c++,unicode,string-literals,C++,Unicode,String Literals,在gcc上调试时,我发现Unicode文本u“万不得已"表示为u“\007\116\015\116\227\137\362\135”。这很有意义--万为0x4E07,八进制中的0x4E为116 现在,在英特尔驱动的Macbook上的Apple LLVM 9.1.0上,我发现相同的文字不能作为相同的字符串处理,即: u16string{u"万不得已"} == u16string{u"\007\116\015\116\227\137\362\135"} 从true到false。我仍然使用一个小小的

在gcc上调试时,我发现Unicode文本
u“万不得已"表示为
u“\007\116\015\116\227\137\362\135”
。这很有意义--
为0x4E07,八进制中的0x4E为116

现在,在英特尔驱动的Macbook上的Apple LLVM 9.1.0上,我发现相同的文字不能作为相同的字符串处理,即:

u16string{u"万不得已"} == u16string{u"\007\116\015\116\227\137\362\135"}
true
false
。我仍然使用一个小小的endian系统,所以我不知道发生了什么

注意,我不是想用通信
u“万不得已“
=
u”\007\116\015\116\227\137\362\135”
。我只是想了解发生了什么

我发现Unicode文本
u“万不得已“
表示为
u”\007\116\015\116\227\137\362\135”

不,事实上不是。这就是为什么

u“…”
字符串文字在所有平台上编码为基于
char16\u t
的UTF-16编码字符串(这就是
u
前缀的具体含义)

u”万不得已“
由以下UTF-16代码单元序列表示:

4E07 4E0D 5F97 5DF2
07 4E 0D 4E 97 5F F2 5D
0007 004E 000D 004E 0097 005F 00F2 005D
在little endian系统中,UTF-16序列由以下原始字节序列表示:

4E07 4E0D 5F97 5DF2
07 4E 0D 4E 97 5F F2 5D
0007 004E 000D 004E 0097 005F 00F2 005D
在八进制中,只有在使用基于字符的
字符串时,才会用
“\007\116\015\116\227\137\362\135”
表示(请注意,缺少字符串前缀,或者
u8
也适用于本例)

u“\007\116\015\116\227\137\362\135”
不是基于
char
的字符串!它是基于
char16\u t
字符串,其中每个八进制数代表一个单独的UTF-16代码单元。因此,该字符串实际上代表这个UTF-16代码单元序列:

4E07 4E0D 5F97 5DF2
07 4E 0D 4E 97 5F F2 5D
0007 004E 000D 004E 0097 005F 00F2 005D
这就是为什么两个
u16string
对象不作为相同的字符串值进行比较的原因,因为它们实际上并不相等


您可以在这里看到这一点:

Unicode是Unicode,编码是编码。@πάνταῥεῖ : 这意味着什么?为什么编译器之间的编码不同?xaxxon:updated.live code:这很有意义。这意味着调试器是错误的。我现在不明白的是,为什么gcc上保持等价性。(Cygwin上的gcc 7.3.0。)请注意,我只是重新运行测试以确认gcc行为。@Mohan这意味着调试器正在显示
u16string
的原始字节(如果调试器不支持将
char16\t
数据显示为普通字符,这是有意义的),并以八进制(奇数,为什么不是十六进制?),但我不希望它在这样一个原始字符串上包含
u
前缀。但是
u16string{u'万不得已“}==u16string{u”\007\116\015\116\227\137\362\135}
在任何编译器上都应该是正确的。如果是,这是一个应该向编译器供应商报告的错误。它确实包含u前缀。现在您已经指出这是一个错误。@Mohan调试器可能会显示
u
前缀,因为数据是
char16\u t
,但随后它会显示原始的8bit bytes而不是本机16位值,因为
char16\u t
可以高达0xFFFF(十进制65535),所以大多数值太大,无法以八进制处理,八进制的最大值为0x1FF(十进制511)。