Ce face wchar_t, char8_t, char16_t, char32_t
Un char are doar 8 biți, prea puțin pentru toate literele lumii. De aceea C++ are tipuri de caractere pentru codificările Unicode, fiecare cu prefixul lui de literal: u8"..." pentru char8_t (UTF-8), u"..." pentru char16_t (UTF-16) și U"..." pentru char32_t (UTF-32). Șirurile corespunzătoare sunt std::u8string, std::u16string și std::u32string.
În UTF-32 fiecare caracter ocupă exact un char32_t, deci lungimea șirului este chiar numărul de litere. În UTF-8 și UTF-16 un caracter poate ocupa mai multe unități.
wchar_t (prefixul L) este mai vechi și are mărimi diferite: 2 octeți pe Windows (unde API-ul sistemului îl folosește peste tot) și 4 octeți pe Linux și macOS. În cod portabil, preferă char cu UTF-8 sau tipurile char8_t/char16_t/char32_t.
Exemple
Exemplul 1: Același cuvânt în patru codificări
„Iași” are 4 litere. În UTF-8, „ș” ocupă 2 unități, deci 5 în total; în UTF-16 și UTF-32 fiecare literă ocupă o unitate. Mărimea lui wchar_t este cea de pe macOS.
#include <print>
#include <string>
int main() {
std::u8string s8 = u8"Iași";
std::u16string s16 = u"Iași";
std::u32string s32 = U"Iași";
std::wstring sw = L"Iași";
std::println("UTF-8: {} unități de {} octet", s8.size(), sizeof(char8_t));
std::println("UTF-16: {} unități de {} octeți", s16.size(), sizeof(char16_t));
std::println("UTF-32: {} unități de {} octeți", s32.size(), sizeof(char32_t));
std::println("wchar_t: {} unități de {} octeți", sw.size(), sizeof(wchar_t));
}
Rezultat
UTF-8: 5 unități de 1 octet
UTF-16: 4 unități de 2 octeți
UTF-32: 4 unități de 4 octeți
wchar_t: 4 unități de 4 octeți
Exemplul 2: Codul Unicode al unei litere
Un char32_t ține codul Unicode complet. „ș” cu virgulă (cel corect în română) are codul U+0219, iar varianta veche, cu sedilă, are U+015F: pentru calculator sunt litere diferite.
#include <print>
int main() {
char32_t s_virgula = U'ș';
char32_t t_virgula = U'ț';
std::println("ș are codul U+{:04X}", static_cast<unsigned>(s_virgula));
std::println("ț are codul U+{:04X}", static_cast<unsigned>(t_virgula));
}
Rezultat
ș are codul U+0219
ț are codul U+021B
Greșeli frecvente
- Încerci să afișezi un
std::u8stringcustd::coutsaustd::println. Din C++20,char8_teste un tip separat și nu se afișează direct; pentru afișare foloseștestd::stringobișnuit (care în practică conține tot UTF-8). - Presupui că
wchar_tare aceeași mărime peste tot. Un fișier scris cuwchar_tpe Windows (2 octeți) nu se citește corect pe Linux (4 octeți).
Comenzi înrudite
char: Tipul pentru un singur caracter (un octet); în spate este un număr mic, codul caracterului.sizeof: Dă numărul de octeți ocupați în memorie de un tip sau de o variabilă; se calculează la compilare.signed, unsigned, short, long: Modificatori care schimbă mărimea (short, long) sau semnul (signed, unsigned) tipurilor întregi.std::string: Șir de caractere care își gestionează singur memoria; atenție, lucrează cu octeți, nu cu litere.