【问题标题】:How do I correctly initialize wide character string?如何正确初始化宽字符串?
【发布时间】:2019-09-11 16:32:51
【问题描述】:

我正在尝试找出 c 中的宽字符。例如,我测试一个包含单个字母“Ē”的字符串,该字符串在 utf8 中编码为 c492。

char* T1 = "Ē";
//This is the resulting array { 0xc4, 0x92, 0x00 }

wchar_t* T2 = L"Ē";
//This is the resulting array { 0x00c4, 0x2019, 0x0000 }

我希望第二个数组是 {0xc492, 0x0000},但它包含一个额外的字符,在我看来只是浪费空间。谁能帮我理解这是怎么回事?

【问题讨论】:

  • 源文件使用哪种编码方式保存?
  • 如果有的话,我希望第二个数组是 {0x0112, 0x0000},即 utf-16 或 utf-32 编码。我不知道应该使用什么编码 { 0x00c4, 0x2019, 0x0000 }。
  • 字符 0xC492 看起来像这样
  • 另外,请注意字符串文字是 const 字符的数组。您的代码正在使用从字符串文字到指向字符的指针的不推荐转换。这曾经仅出于与 C 向后兼容的原因而工作,并在 C++11 中被删除。不要这样做。字符串文字的内容不得修改。让你的指针指向const 个字符……
  • 此外,这甚至可以编译的事实表明您必须使用古老的编译器。您可能想考虑升级...

标签: c++ c string char


【解决方案1】:

您在这里设法做的是 mojibake。您的源代码是用 UTF-8 编写的,但它是在 Windows 代码页 1252 中解释的(即编译器源字符集是 CP1252)。

宽字符串内容是 UTF-8 字节 0xC4 0x92 转换为 UCS-2 的 Windows 代码页 1252 字符。 最简单的方法就是使用转义符:

wchar_t* T2 = L"\x112";

wchar_t* T2 = L"\u0112";

更大的问题是,据我所知,C 和 C++ 都没有在代码本身中指定源字符集的机制,因此它始终是您可以轻松复制粘贴的外部设置或选项。

【讨论】:

  • 更简单的方法是将文件保存为 UTF-8 和 BOM,而不是使用十六进制转义符。
  • @n.m.确保代码在任何地方都不起作用的最简单方法...
  • 请找到一个默认情况下不起作用的实现。
  • @AnttiHaapala 除了在 MSVC 中没有其他任何地方。记录了 MSVC 通过 BOM 的存在来检测 UTF-8 编码的源文件的行为。你仍然是对的,这不符合 UTF-8 标准(它不允许忽略文件开头的 U+FEFF 字符(BOM))和 ANSI C(它在开头定义 U+FEFF的文件是语法错误)。
  • @n.m.好的,所以你不正确。 BOM 被 Clang 和 GCC忽略,TCC 不会忽略它,这会导致语法错误。 IE。 只有 MSVC,这有任何影响。 GCC 和 Clang 使用 UTF-8 作为源字符集,除非语言环境另有提示,在这种情况下它们会忽略 BOM。
【解决方案2】:

您的编译器将您的源代码文件(保存为 UTF-8)误解为 Windows-1252(通常称为 ANSI)。它不会将字节序列C4 92 解释为一个字符的UTF-8 字符串“Ē”,而是解释为两个字符的Windows-1252 字符串"Ä’""Ä"的unicode codepoint是U+00C4,"’"的unicode codepoint是U+2019。这正是您在宽字符串中看到的内容。

8 位字符串仅适用,因为字符串的误解无关紧要,因为它在编译期间不会转换。编译器将字符串读取为 Windows-1252 并将字符串作为 Windows-1252 发出(因此它不需要转换任何内容,并将两者都视为“Ä'”)。您将二进制文件中的源代码和数据解释为 UTF-8,因此您认为两者都是 "Ē"

要让编译器将您的源代码视为 UTF-8,请使用开关 /utf-8

顺便说一句:在宽字符串中观察到的正确 UTF-16 编码(这是 MSVC 用于宽字符串的编码)不是{0xc492, 0x0000},而是{0x0112, 0x0000},因为"Ē"U+0112

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2010-11-11
    • 1970-01-01
    • 2011-06-20
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多