char vs wchar_t vs char16_t vs char32_t (c++11) (Programare, C++, C++11)

user904963 a intrebat.

Din câte am înțeles, un char este sigur pentru a găzdui caractere ASCII, în timp ce char16_t și char32_t sunt sigure pentru a găzdui caractere din Unicode, unul pentru varietatea de 16 biți și altul pentru varietatea de 32 de biți (Ar fi trebuit să spun „a” în loc de „the”?). Dar apoi rămân să mă întreb care este scopul din spatele wchar_t este. Ar trebui să folosesc vreodată acest tip în codul nou sau este pur și simplu acolo pentru a sprijini codul vechi? Care a fost scopul lui wchar_t în codul vechi dacă, din câte am înțeles, dimensiunea sa nu avea garanția că este mai mare decât un char? Clarificări ar fi binevenite!

2 răspunsuri
bames53

char este pentru unități de cod pe 8 biți, char16_t este pentru unități de cod pe 16 biți, iar char32_t este pentru unități de cod pe 32 de biți. Oricare dintre acestea poate fi utilizat pentru „Unicode”; UTF-8 utilizează unități de cod pe 8 biți, UTF-16 utilizează unități de cod pe 16 biți, iar UTF-32 utilizează unități de cod pe 32 de biți.


Garanția oferită pentru wchar_t a fost că orice caracter acceptat într-o locație poate fi convertit din char în wchar_t, iar orice reprezentare era folosită pentru char, fie că era vorba de mai mulți octeți, coduri de deplasare, ce mai era nevoie, se putea utiliza wchar_t ar fi o valoare unică, distinctă. Scopul acestui lucru era că astfel se putea manipula wchar_t șiruri de caractere la fel ca și algoritmii simpli utilizați cu ASCII.

De exemplu, conversia ascii în majuscule se face astfel:

auto loc = std::locale("");

char s[] = "hello";
for (char &c : s) {
  c = toupper(c, loc);
}

Dar acest lucru nu va permite convertirea tuturor caracterelor din UTF-8 în majuscule sau a tuturor caracterelor din alte codificări, cum ar fi Shift-JIS. Oamenii au dorit să poată internaționaliza acest cod astfel:

auto loc = std::locale("");

wchar_t s[] = L"hello";
for (wchar_t &c : s) {
  c = toupper(c, loc);
}

Deci, fiecare wchar_t este un „caracter” și dacă are o versiune cu majuscule, atunci poate fi convertit direct. Din păcate, acest lucru nu funcționează întotdeauna; de exemplu, există ciudățenii în unele limbi, cum ar fi litera germană ß, unde versiunea cu majuscule este de fapt formată din două caractere SS în loc de un singur caracter.

Așadar, manipularea textului internaționalizat este în mod intrinsec mai dificilă decât ASCII și nu poate fi simplificată în modul în care au făcut-o proiectanții de la wchar_t intenționau. Ca atare wchar_t și, în general, caracterele largi oferă o valoare redusă.

Singurul motiv pentru a le folosi este faptul că au fost integrate în unele API-uri și platforme. Cu toate acestea, prefer să rămân la UTF-8 în propriul meu cod chiar și atunci când dezvolt pe astfel de platforme și să convertesc doar la limitele API în orice codificare este necesară.

Comentarii

  • Îmi place comentariul tău și comentariul lui Kuhl, ambele au informații unice. Mi-aș dori să pot da două controale verzi. Va trebui să mă gândesc mai bine pentru a decide cine o primește. Este protocolul standard pe stackoverflow să nu dai nici o bifă în caz de egalitate? –  > Por user904963.
  • „litera germană ß, unde versiunea cu majuscule este de fapt cele două caractere SS” – Asta nu este chiar corect. Versiunea cu majuscule a lui „ß” este „ẞ” (U+1E9E: litera majusculă latină S ascuțit). Aceasta a fost introdusă odată cu Unicode 5.1 (a se vedea Operațiuni de casare adaptate pentru referință). În timp ce casarea implicită Unicode face ca „ß” să fie majusculă la „SS”, aceasta nu este cu adevărat versiunea cu majuscule. –  > Por IInspectabil.
  • @IInspectable Utilizarea lui „SS” nu este o invenție a algoritmului de casare Unicode. Ea se bazează pe utilizarea reală. Utilizarea „SS” și „SZ” a fost o practică obișnuită, iar algoritmii Unicode au fost concepuți pentru a respecta acest lucru. Din documentația Unicode la care faceți legătura „În special, s majusculă ascuțit este destinat reprezentărilor tipografice ale semnelor și titlurilor cu majuscule, precum și altor medii în care utilizatorii cer ca s-ul ascuțit să fie păstrat în majuscule. În general, o astfel de utilizare este rară.” –  > Por bames53.
  • @IInspectable Dar ai dreptate, din punct de vedere tehnic, „ß” nu are majusculă tradițională, iar utilizarea lui „SS” sau „SZ” provine din faptul că „ss” sau „sz” este folosit ori de câte ori caracterul „ß” nu este disponibil (de exemplu, atunci când se scrie în germană cu o tastatură care nu are tasta „ß”). Deoarece în mod tradițional nu există un ß cu majusculă, practica a fost de a scrie cu majusculă înlocuitorii obișnuiți „ss” și „sz” pentru a obține forma majusculă a lui „ß”. –  > Por bames53.
  • ß în mod tradițional nu are majusculă, deoarece nu este o literă, ci o ligatură a s-ului tradițional minuscul (scris ca o bară verticală în fraktur) și a unui z minuscul. De aceea se numește esszet în germană. Majuscula „ẞ”, introdusă odată cu Unicode 5.1, există doar pentru casarea titelului. Majuscula în textul propriu-zis nu o va folosi niciodată. –  > Por Patrick Schlüter.
Dietmar Kühl

Tipul wchar_t a fost introdus în standard atunci când Unicode a promis că va crea o reprezentare pe 16 biți. Majoritatea furnizorilor aleg să facă wchar_t 32 de biți, dar un furnizor mare a ales să o facă pe 16 biți. Deoarece Unicode utilizează mai mult de 16 biți (de exemplu, 20 de biți), s-a considerat că ar trebui să avem tipuri de caractere mai bune.

Intenția pentru char16_t este de a reprezenta UTF16 și char32_t este menit să reprezinte direct caracterele Unicode. Cu toate acestea, pe sistemele care utilizează wchar_t ca parte a interfeței lor fundamentale, veți fi blocat cu wchar_t. Dacă nu sunteți constrâns, eu personal aș folosi char pentru a reprezenta Unicode folosind UTF8. Problema cu char16_t și char32_t este că acestea nu sunt pe deplin acceptate, nici măcar în biblioteca standard C++: de exemplu, nu există fluxuri care să suporte aceste tipuri în mod direct și necesită mai mult efort decât simpla instanțiere a fluxului pentru aceste tipuri.

Comentarii

  • Lipsa de suport pentru char16_t și char32_t în standard se datorează faptului că standardul nu prevede un astfel de suport sau se datorează faptului că tipurile sunt noi, ceea ce înseamnă că suportul va veni cu timpul? –  > Por utilizator904963.
  • @user904963: Revizuirea actuală nu impune denumiri pentru tipurile char16_t și char32_t versiuni. Se pare că impune totuși fațetele necesare, ceea ce înseamnă că fluxurile ar putea fi utilizate. Nu am văzut propuneri de îmbunătățire a suportului, dar asta nu înseamnă că comitetul se opune adăugării suportului, adică ar putea veni. –  > Por Dietmar Kühl.
  • Suportul complet pentru char16_t și char32_t nu a ajuns niciodată. –  > Por hdante.

Tags:,