Po pokrewnym pytaniu chciałbym zapytać o nowe typy literałów znakowych i łańcuchowych w C ++ 11. Wygląda na to, że mamy teraz cztery rodzaje znaków i pięć rodzajów literałów tekstowych. Typy postaci:
char a = '\x30'; // character, no semantics
wchar_t b = L'\xFFEF'; // wide character, no semantics
char16_t c = u'\u00F6'; // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF'; // 32-bit, assumed UCS-4
I literały ciągów:
char A[] = "Hello\x0A"; // byte string, "narrow encoding"
wchar_t B[] = L"Hell\xF6\x0A"; // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6"; // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto E[] = u8"\u00F6\U0010FFFF"; // (3)
Pytanie brzmi: czy odwołania do znaków \x
/ \u
/ można \U
dowolnie łączyć ze wszystkimi typami łańcuchów? Czy wszystkie typy łańcuchów mają stałą szerokość, tj. Tablice zawierają dokładnie tyle elementów, ile występuje w literale, czy też odwołania do \x
/ \u
/ \U
są rozszerzane do zmiennej liczby bajtów? Czy u""
i u8""
łańcuchy znaków mają semantykę kodowania, np. Czy mogę powiedzieć char16_t x[] = u"\U0010FFFF"
, a punkt kodowy inny niż BMP zostaje zakodowany w dwuczęściowej sekwencji UTF16? I podobnie dla u8
? W (1), czy mogę pisać samotne surogaty z \u
? Wreszcie, czy którakolwiek z funkcji kodowania znaków jest świadoma (tj. Rozpoznają znaki i mogą wykrywać nieprawidłowe sekwencje bajtów)?
To jest trochę otwarte pytanie, ale chciałbym uzyskać możliwie pełny obraz nowego kodowania UTF i funkcji typu nowego C ++ 11.
u"\U0010FFFF"
w parę zastępczą.Odpowiedzi:
Nie
\x
można używać w czymkolwiek, ale\u
i\U
można go używać tylko w łańcuchach, które są specjalnie zakodowane w formacie UTF. Jednak dla dowolnego ciągu zakodowanego w formacie UTF\u
i\U
może być używany według własnego uznania.Nie w sposób, jaki masz na myśli.
\x
,\u
i\U
są konwertowane na podstawie kodowania ciągów. Liczba tych „jednostek kodu” (przy użyciu terminów Unicode. Achar16_t
jest jednostką kodu UTF-16) zależy od kodowania ciągu zawierającego. Literału8"\u1024"
utworzyłby ciąg zawierający 2char
s plus terminator zerowy. Literału"\u1024"
utworzyłby ciąg zawierający 1char16_t
plus terminator zerowy.Liczba używanych jednostek kodu jest oparta na kodowaniu Unicode.
u""
tworzy ciąg zakodowany w formacie UTF-16.u8""
tworzy ciąg zakodowany w formacie UTF-8. Zostaną zakodowane zgodnie ze specyfikacją Unicode.Absolutnie nie. Specyfikacja wyraźnie zabrania używania par zastępczych UTF-16 (0xD800-0xDFFF) jako punktów kodowych dla
\u
lub\U
.Absolutnie nie. Cóż, pozwól mi to przeformułować.
std::basic_string
nie zajmuje się kodowaniem Unicode. Z pewnością mogą przechowywać ciągi zakodowane w UTF. Ale mogą myśleć tylko o nich jako sekwencjechar
,char16_t
lubchar32_t
; nie mogą myśleć o nich jako o sekwencji punktów kodowych Unicode, które są zakodowane za pomocą określonego mechanizmu.basic_string::length()
zwróci liczbę jednostek kodu, a nie punktów kodowych. I oczywiście, funkcje ciągów w standardowej bibliotece C są całkowicie bezużyteczneNależy jednak zauważyć, że „długość” łańcucha Unicode nie oznacza liczby punktów kodowych. Niektóre punkty kodowe łączą „znaki” (niefortunna nazwa), które łączą się z poprzednim punktem kodowym. Tak więc wiele punktów kodowych może odpowiadać pojedynczemu znakowi wizualnemu.
Iostreams może w rzeczywistości odczytywać / zapisywać wartości zakodowane w Unicode. Aby to zrobić, będziesz musiał użyć ustawień regionalnych, aby określić kodowanie i odpowiednio nasycić je w różnych miejscach. Łatwiej to powiedzieć niż zrobić, a nie mam na sobie żadnego kodu, aby pokazać ci, jak to zrobić.
źródło
\x
nie można go używać z niczym, na przykład U + 1F984 nie będzie działać z prefiksem \ x\u
i\U
nie może być używane ze znakami sterującymi ASCII, przynajmniej w Clang.