C++ C++;:Unicode字符串文本的可移植性
在gcc上调试时,我发现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。我仍然使用一个小小的
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)。