конфликты: определение строки wchar_t в стандарте C ++ и реализация Windows? - PullRequest
7 голосов
/ 08 декабря 2010

От c ++ 2003 2.13

Широкий строковый литерал имеет тип « массив n const wchar_t » и имеет статическую продолжительность хранения, гдеn - размер строки, как определено ниже

Размер литерала широкой строки - это общее количество escape-последовательностей, имен универсальных символов и других символов, плюс один для завершающего L '\ 0'.

Из c ++ 0x 2.14.5

Широкий строковый литерал имеет тип « массив n const wchar_t », где nэто размер строки, как определено ниже

Размер литерала char32_t или широкой строки - это общее количество escape-последовательностей, имен универсальных символов и других символов, плюс один для завершающего U '\0 'или L' \ 0 '.

Размер строкового литерала char16_t представляет собой общее количество escape-последовательностей, имен универсальных символов и других символов, плюс по одному для каждого символа, требующего суррогатную пару, плюс один для завершающего u '\ 0'.

Утверждение в C ++ 2003 довольно расплывчато.Но в C ++ 0x, при подсчете длины строки, широкий строковый литерал wchar_t должен обрабатываться так же, как char32_t, и отличаться от char16_t.

Есть пост, в котором четко указано, как windows реализует wchar_t вhttps://stackoverflow.com/questions/402283?tab=votes%23tab-top

Короче говоря, wchar_t в окнах имеет размер 16 бит и кодируется с использованием UTF-16.Стандартное утверждение, очевидно, оставляет что-то противоречивое в Windows.

, например,

wchar_t kk[] = L"\U000E0005";

Это превышает 16 битов, а для UTF-16 ему требуется два 16 битов для его кодирования (суррогатная пара).

Однако из стандартного, kk - это массив из 2 wchar_t (1 для универсального имени \ U000E005, 1 для \ 0).

Но во внутренней памяти Windows требуется 3 16-битных объекта wchar_t для его хранения, 2 wchar_tдля суррогатной пары и 1 wchar_t для \ 0.Следовательно, из определения массива, kk - это массив из 3 wchar_t.

Это явно противоречит друг другу.

Я думаю, что самое простое решение для Windows - это «запретить» все, что требует суррогатную парув wchar_t («забанить» любой юникод вне BMP).

Что-то не так с моим пониманием?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 08 декабря 2010

Стандарт требует, чтобы wchar_t был достаточно большим, чтобы содержать любой символ в поддерживаемом наборе символов. Исходя из этого, я думаю, что ваша предпосылка правильна - неправильно для VC ++ представлять один символ \U000E0005, используя два wchar_t блока.

Символы вне BMP используются редко, и сама Windows внутренне использует кодировку UTF-16, поэтому для VC ++ просто удобно (даже если неправильно) вести себя таким образом. Однако вместо того, чтобы «запрещать» такие символы, скорее всего, в будущем размер wchar_t увеличится, а char16_t займет свое место в Windows API.

Ответ, на который вы ссылались, также несколько вводит в заблуждение:

В Linux wchar_t - это 4 байта, а в Windows - 2 байта

Размер wchar_t зависит исключительно от компилятора и не имеет ничего общего с операционной системой. Просто так получается, что VC ++ использует 2 байта для wchar_t, но, опять же, в будущем это вполне может измениться.

2 голосов
/ 08 декабря 2010

Windows ничего не знает о wchar_t, потому что wchar_t - это концепция программирования. И наоборот, wchar_t - это просто хранилище, и оно ничего не знает о семантическом значении данных, которые вы в нем храните (то есть ничего не знает о Unicode, ASCII и т. Д.)

Если компилятор или SDK, предназначенный для Windows, определяет wchar_t как 16 бит, то этот компилятор может конфликтовать со стандартом C ++ 0x. (Я не знаю, есть ли какие-то предложения get-out, которые позволяют wchar_t быть 16 битами.) Но в любом случае компилятор может определить wchar_t как 32 бита (чтобы соответствовать стандарту) и предоставить функции времени выполнения для преобразования / из UTF-16 для случаев, когда вам нужно передать ваш wchar_t * в API Windows.

...