wchar_t在visual studio中是2个字节,存储UTF-16。 Unicode感知应用程序如何使用U + FFFF以上的字符?

时间:2010-12-07 12:58:39

标签: visual-studio-2010 visual-c++ unicode buffer-overflow wchar-t

我们正在计划让我们的应用程序识别Unicode,我们正在分析我们将遇到的问题。

特别是,我们的应用程序将严重依赖字符串的长度,我们希望使用wchar_t作为基本字符类。

当处理必须以UTF-16中的2个16位为单位存储的字符时出现问题,即U + 10000以上的字符。

简单示例:

我有UTF-8字符串“蟂”(Unicode字符U + 87C2,UTF-8:E8 9F 82)

所以,我设置了以下代码:

const unsigned char my_utf8_string[] = { 0xe8, 0x9f, 0x82, 0x00 };

// compute size of wchar_t buffer.
int nb_chars = ::MultiByteToWideChar(CP_UTF8,                                  // input is UTF8
                                     0,                                        // no flags
                                     reinterpret_cast<char *>(my_utf8_string), // input string (no worries about signedness)
                                     -1,                                       // input is zero-terminated
                                     NULL,                                     // no output this time
                                     0);                                       // need the necessary buffer size

// allocate
wchar_t *my_utf16_string = new wchar_t[nb_chars];

// convert
nb_chars = ::MultiByteToWideChar(CP_UTF8,
                                 0,
                                 reinterpret_cast<char *>(my_utf8_string),
                                 -1,
                                 my_widechar_string, // output buffer
                                 nb_chars);          // allocated size

好的,这可行,它分配两次16位,而wchar_t的缓冲区包含{0x87c2,0x0000}。如果我将它存储在std::wstring内并计算大小,我会得到1。

现在,让我们将字符(U + 104A2)作为输入,采用UTF-8:F0 90 92 A2。

这次,它为三个wchar_t和std :: wstring :: size返回2 分配空间,即使我认为我只有一个字符

这是有问题的。我们假设我们以UTF-8接收数据。我们可以简单地通过不计算等于10xxxxxx的字节来计算Unicode字符。我们希望在wchar_t数组中导入该数据以使用它。如果我们只是分配字符数加1,那么可能是安全的...直到有人使用U + FFFF以上的字符。然后我们的缓冲区将太短,我们的应用程序将崩溃。

因此,使用以不同方式编码的相同字符串,计算字符串中字符数的函数将返回不同的值吗?

如何设计适用于Unicode字符串的应用程序以避免这种烦恼?

感谢您的回复。

2 个答案:

答案 0 :(得分:6)

你必须接受std :: wstring :: size 给出字符数。相反,它为您提供了代码单元的数量。如果您有16位代码单元,它将确定您在字符串中有多少代码单元。计算Unicode字符的数量需要在字符串上循环。一旦你接受它就不再烦人了。

至于计算UTF-8中的字符:不要。相反,您发布的代码很好:调用MultiByteToWideChar一次会告诉您需要多少代码单元,然后分配正确的数字 - 无论是BMP字符还是辅助平面。如果您绝对想要编写自己的计数例程,请使用其中两个:一个计算字符数,另一个计算16位代码单位数。如果前导字节是11110xxx,则需要计算两个代码单元。

答案 1 :(得分:3)

我建议您阅读官方Unicode网站上的以下常见问题解答:http://www.unicode.org/faq//utf_bom.html

基本上,区分代码单元,代码点和字符非常重要。