2010-12-08 15 views
7

z C++ 2003 2,13: definicja ciągu wchar_t w standardzie C++ i implementacja Windows?

szeroki Łańcuch znaków ma typ „układ n const wchar_t” i ma statyczną czas przechowywania, w którym n oznacza wielkość łańcuchu, jak zdefiniowano poniżej

Wielkość literału o szerokim łańcuchu oznacza całkowitą liczbę sekwencji unikowych, uniwersalnych znaków i innych znaków, a także jedną dla kończącego L '\ 0'.

z C++ 0x 2.14.5

szeroki Łańcuch znaków ma typ „układ n const wchar_t”, gdzie n oznacza wielkość łańcuchu, jak zdefiniowano poniżej

The rozmiar liter char32_t lub literał o szerokim łańcuchu jest całkowitą liczbą sekwencji escape, uniwersalnych znaków i innych znaków plus jeden dla kończącego U '\ 0' lub L '\ 0'.

Wielkość literału ciągu char16_t to całkowita liczba sekwencji escape, nazw uniwersalnych znaków i innych znaków, plus jedna dla każdego znaku wymagającego pary zastępczej plus jedna dla kończącego znaku u '\ 0'.

Oświadczenie w C++ 2003 jest dość niejasne. Ale w C++ 0x, przy zliczaniu długości łańcucha, szeroki tekst literowy wchar_t będzie traktowany tak samo jak char32_t i inny niż char16_t.

Jest post, który stwierdza wyraźnie, jak okna realizuje wchar_t w https://stackoverflow.com/questions/402283?tab=votes%23tab-top

w skrócie, wchar_t w oknach jest 16 bitów i zakodowane przy użyciu UTF-16. Oświadczenie w standardzie najwyraźniej pozostawia coś sprzecznego w systemie Windows.

np

wchar_t kk[] = L"\U000E0005"; 

ta przekracza 16 bitów i UTF-16 potrzebuje dwa bity do 16 go (surogat para) kodowania.

Jednak ze standardu kk jest tablicą 2 wchar_t (1 dla nazwy uniwersalnej \ U000E005, 1 dla \ 0).

Jednak w pamięci wewnętrznej Windows potrzebuje 3 16-bitowych obiektów wchar_t do przechowywania, 2 wchar_t dla pary zastępczej i 1 wchar_t dla \ 0. Dlatego z definicji tablicy kk jest tablicą 3 wchar_t.

To najwyraźniej sprzeczne ze sobą.

Myślę, że jednym z najprostszych rozwiązań dla systemu Windows jest "blokowanie" wszystkiego, co wymaga zastępczej pary w wchar_t ("zakaz" dowolnego unicodu poza BMP).

Czy coś jest nie tak z moim zrozumieniem?

Dzięki.

Odpowiedz

3

Standard wymaga, aby wchar_t był wystarczająco duży, aby pomieścić dowolny znak w obsługiwanym zestawie znaków.Opierając się na tym, myślę, że twoje założenie jest poprawne - błędem jest, aby VC++ reprezentował pojedynczą postać \U000E0005 używając dwóch jednostek wchar_t.

Znaki spoza BMP są rzadko używane, a sam system Windows używa kodowania UTF-16, więc po prostu jest to wygodne (nawet jeśli jest niepoprawne), aby VC++ zachowywał się w ten sposób. Jednak zamiast "banować" takie znaki, prawdopodobnie rozmiar wchar_t wzrośnie w przyszłości, natomiast char16_t zajmie miejsce w interfejsie API systemu Windows.

Odpowiedź jesteś związana jest nieco mylące, a także:

Na Linux, wchar_t jest 4-bajtów, podczas gdy w systemie Windows, to 2-bajty

Wielkość wchar_t zależy wyłącznie na kompilatorze i nie ma nic wspólnego z systemem operacyjnym. Zdarza się, że VC++ używa 2 bajty dla wchar_t, ale po raz kolejny może to bardzo zmienić w przyszłości.

+0

dziękuję. mam to teraz. Czasami trudno jest zrozumieć nową koncepcję, ale kiedy już ją otrzymasz, staje się prostsza natychmiast. – user534498

+0

Windows technicznie używa 'WCHAR', a nie' wchar_t'. W przeszłości był on niepoprawnie pisany jako "unsigned short" i mógł stać się "char16_t" w przyszłości. Ale szczerze mówiąc, nie widzę, żeby tak się działo - literały łańcuchowe pękną. – MSalters

+0

@MSalters: Dlaczego ciąg literałów miałby się rozpaść? Właśnie takie są makra 'TEXT (" ... ")' - ludzie nigdy nie powinni używać surowego 'L" ... '' literałów. Ponadto, przynajmniej na VS2005, 'WCHAR' jest typedef dla' wchar_t', a nie 'unsigned short'. – casablanca

1

Windows nic nie wie o wchar_t, ponieważ wchar_t jest pojęciem programowania. Odwrotnie, wchar_t to po prostu pamięć i nic nie wie o wartości semantycznej przechowywanych w nim danych (to znaczy, że nic nie wie o Unicode lub ASCII lub czymkolwiek.)

Jeśli kompilator lub pakiet SDK przeznaczony dla systemu Windows definiuje wchar_t to 16 bitów, wtedy ten kompilator może być w konflikcie ze standardem C++ 0x. (Nie wiem, czy istnieją pewne klauzule, które pozwalają wchar_t na 16 bitów.) Ale w każdym przypadku kompilator może zdefiniować wchar_t na 32 bity (w celu zachowania zgodności z normą) i zapewnić funkcje wykonawcze do konwersji na/od UTF-16, gdy musisz przekazać wchar_t * do Windows API.