【问题标题】:Size of wchar_t* for surrogate pair (Unicode character out of BMP) on WindowsWindows 上代理对(BMP 中的 Unicode 字符)的 wchar_t* 大小
【发布时间】:2012-07-15 06:40:56
【问题描述】:

我在 Windows 8 上遇到了一个有趣的问题。我测试了我可以用 wchar_t* 字符串表示 BMP 之外的 Unicode 字符。以下测试代码对我产生了意想不到的结果:

const wchar_t* s1 = L"a";
const wchar_t* s2 = L"\U0002008A"; // The "Han" character

int i1 = sizeof(wchar_t); // i1 == 2, the size of wchar_t on Windows.

int i2 = sizeof(s1); // i2 == 4, because of the terminating '\0' (I guess).
int i3 = sizeof(s2); // i3 == 4, why?

U+2008A 是Han character,它不在二进制多语言窗格中,因此它应该由 UTF-16 中的代理对表示。这意味着 - 如果我理解正确的话 - 它应该由两个 wchar_t 字符表示。所以我预计 sizeof(s2) 为 6(代理对的两个 wchar_t-s 为 4,终止 \0 为 2)。

那么为什么 sizeof(s2) == 4?我测试了s2字符串构造正确,因为我用DirectWrite渲染过,汉字符显示正确。

更新:正如 Naveen 指出的,我试图错误地确定数组的大小。以下代码产生正确的结果:

const wchar_t* s1 = L"a";
const wchar_t* s2 = L"\U0002008A"; // The "Han" character

int i1 = sizeof(wchar_t); // i1 == 2, the size of wchar_t on Windows.

std::wstring str1 (s1);
std::wstring str2 (s2);

int i2 = str1.size(); // i2 == 1.
int i3 = str2.size(); // i3 == 2, because two wchar_t characters needed for the surrogate pair.

【问题讨论】:

    标签: c++ windows unicode utf-16


    【解决方案1】:

    sizeof(s2) 返回存储指针 s2 或任何其他指针所需的字节数,在您的系统上为 4 个字节。它与s2指向的存储在中的字符无关。

    【讨论】:

    • "它与存储在s2中的字符无关" -- 由于问题是由于指针与指向的事物之间的误解引起的,因此您应该避免引起另一个这样的误解。 s2 中没有存储字符。在这种情况下,有一个字符存储在 s2[0] 和 s2[1] 中。如果它不是代理对,那么将有一个字符单独存储在 s2[0] 中,即在 *s2 中。
    【解决方案2】:

    sizeof(wchar_t*) 与sizeof(void*) 相同,即指针本身的大小。在 32 位系统上总是 4,在 64 位系统上总是 8。您需要使用wcslen() 或lstrlenW() 而不是sizeof():

    const wchar_t* s1 = L"a"; 
    const wchar_t* s2 = L"\U0002008A"; // The "Han" character 
    
    int i1 = sizeof(wchar_t); // i1 == 2
    int i2 = wcslen(s1); // i2 == 1
    int i3 = wcslen(s2); // i3 == 2
    

    【讨论】:

    • "sizeof(wchar_t*) is the same as sizeof(void*)" -- 这不是我的理解。 sizeof(char*)、sizeof(signed char*) 和 sizeof(unsigned char*) 的大小都与 sizeof(void*) 相同。 sizeof(wchar_t*) 和 sizeof(other random stuff) 可以小于 sizeof(void*) 取决于实现。
    • @Windowsprogrammer:正确——尽管绝大多数现代编译器使所有指针类型的大小相同。
    • 为什么任何编译器,更不用说 C/C++ 标准,允许任何sizeof(any pointer type) 小于sizeof(void*)?从 sizeof() 的角度来看,指针就是指针,指针就是指针,与它的数据类型无关。
    • @Remy Lebeau 对于现代 C/C++ 来说,允许不同大小类型的指针是一个坏主意。但是举一个潜在用途的例子:在嵌入式世界(一些使用哈佛架构)中,程序和常量数据可能存在于一个地址空间(ROM)中,而非常量数据可能存在于另一个地址空间(RAM)中。 ROM 大小可能为 MBytes,RAM 为 64k。因此,指向函数的指针、const data > 16 位和指向可变数据的指针是 16。我用来玩其他游戏的 PIC 将其全部保留为 16 位,但我想我会就类型的重要性传递一个想法。
    • 当内存非常宝贵时,如果您可以使用更少的字节来存储特定类型的指针,这被认为是一个优势。标准允许的一种设置是使用 16 位 int * 来寻址 65535 ints(尽管我不知道是否有人真的这样做了)
    【解决方案3】:

    答案的附录。
    RE:解开i1 和i2、i3 在问题更新中使用的不同单位。

    i1 值 2 是以 bytes 为单位的大小
    i2 值 1 是以 wchar_t 为单位的大小,IOW 4 字节(假设 @987654326 @ 是 4)。
    i3 值 2 是 wchar_t 中的大小,IOW 8 字节

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-13
      • 2019-01-28
      • 2017-03-06
      • 2012-01-20
      • 2014-11-12
      • 2011-11-21
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多