Размер wchar_t* для суррогатной пары (символ Unicode вне BMP) в Windows
Я столкнулся с интересной проблемой в Windows 8. Я проверял, могу ли я представлять символы Unicode, которые находятся вне BMP, с помощью строк wchar_t*. Следующий тестовый код дал мне неожиданные результаты:
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 - это символ Хан, который находится за пределами Бинарной Многоязычной Панели, поэтому он должен быть представлен суррогатной парой в UTF-16. Что означает - если я правильно понимаю - что он должен быть представлен двумя символами wchar_t. Поэтому я ожидал, что sizeof(s2) будет равен 6 (4 для двух wchar_t-s суррогатной пары и 2 для завершающей \0).
Так почему sizeof(s2) == 4? Я проверил, что строка s2 была построена правильно, потому что я отрисовал ее с помощью DirectWrite, и символ Han был отображен правильно.
ОБНОВЛЕНИЕ: Как указал Навин, я попытался определить размер массивов неправильно. Следующий код дает правильный результат:
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.
3 ответа
sizeof(s2)
возвращает количество байтов, необходимое для хранения указателя s2
или любой другой указатель, который составляет 4 байта в вашей системе. Это не имеет ничего общего с символами, хранящимися в s2
,
sizeof(wchar_t*)
такой же как sizeof(void*)
другими словами, размер самого указателя. Это всегда будет 4 в 32-битной системе и 8 в 64-битной системе. Вам нужно использовать 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
Приложение к ответам.
RE: разгадать различные единицы измерения, использованные в обновлении вопроса, i1
а также i2
, i3
,
i1
значение 2 - размер в байтахi2
значение 1 - это размер в wchar_t, IOW 4 байта (при условии sizeof(wchar_t)
это 4).i3
значение 2 - это размер в wchar_t, IOW 8 байтов