繁体   English   中英

为什么unicode char在std :: string中存储为UTF-8,在wchar_t中存储为UTF-16/32?

[英]Why unicode char is stored as UTF-8 in std::string and UTF-16/32 in wchar_t?

我有一小段代码:

#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>

wchar_t widec('€');
wchar_t widecl(L'€');
std::string tc("€");

int main(int argc, char *argv[])
{
    printf("printf as hex - std::string tc(\"€\") = %x %x %x\n\r", tc.c_str()[0], tc.c_str()[1], tc.c_str()[2]);
    printf("printf as hex - wchar_t widec('€') = %x\n\r", widec);
    printf("printf as hex - wchar_t widecl(L'€') = %x\n\r", widecl);

    return 0;
}

那输出:

printf as hex - std::string tc("€") = ffffffe2 ffffff82 ffffffac
printf as hex - wchar_t widec('€') = e282ac
printf as hex - wchar_t widecl(L'€') = 20ac

我不明白两件事。

  1. 为什么tc.c_str() (它的[0][1][2]索引是准确的)打印为UTF-8,看起来像UTF-16/32,具有前导FF字节?

  2. 为什么初始化相同的wchar_t变量会产生不同的输出,具体取决于是否使用了L前缀,即。 使用它似乎产生UTF-16/32内容和没有L前缀的UTF-8,为什么会这样?

  1. 没有显式符号说明符的char是有signedunsigned ,具体取决于编译器。 该标准没有规定默认类型,它是编译器供应商的选择。

    char传递给print()会将值从8位扩展到32位。 然后%x打印该32位值的位,默认忽略前导零(除非您在%x上使用长度说明符来保留它们)。 8位值如何扩展到32位取决于其实际类型。

    在你的情况下,额外的f你请参阅s是由于char值是符号扩展 0xEx0x8x0xAx都是1,因此1用于在扩展期间填充高24位。 这意味着您的编译器将char实现为signed类型,并将值扩展为signed int 您可以手动将char值类型转换为unsigned以强制它们为零扩展

     printf("printf as hex - std::string tc(\\"€\\") = %x %x %x\\n", (unsigned char) tc[0], (unsigned char) tc[1], (unsigned char) tc[2]); 

    (注意我删除了c_str()的使用,在你的例子中没有必要)

  2. 没有任何前缀的'€'"€"的解释取决于源文件保存为的编码,以及编译器配置为运行的编码。

    如果您的源代码文件以UTF-8保存,那么未加前缀的'€'"€"文字可能是UTF-8的唯一方法是(强制使用UTF-8文字,您可以在C +中使用u8前缀+11及以后)。 以不同的编码保存文件,您将看到不同的结果。 然后将该解释的结果按原样分配给tc ,并按原样编码为widecwchar_t

    另一方面, L前缀强制编译器将L'€'为宽文字而不是窄文字,因此不应该如何解释它。 它知道文字是Unicode,因此它确定了Unicode代码点值,然后在widecl其编码为wchar_t值( wchar_t在Windows上为16位,在其他平台上为32位)。 的Unicode代码点是U+20AC EURO SIGN

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM