Размер 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 байтов

Другие вопросы по тегам