web-dev-qa-db-fra.com

Encodage Unicode pour les littéraux de chaîne en C ++ 11

Après une question connexe , je voudrais poser des questions sur les nouveaux types littéraux de caractères et de chaînes en C++ 11. Il semble que nous ayons maintenant quatre sortes de caractères et cinq sortes de littéraux de chaîne. Les types de caractères:

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

Et les littéraux de chaîne:

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)

La question est la suivante: les \x/\u/\U références de caractères combinables librement avec tous les types de chaînes? Tous les types de chaînes sont-ils de largeur fixe, c'est-à-dire que les tableaux contiennent exactement autant d'éléments que ceux qui apparaissent dans le littéral, ou à \x/\u/\U les références sont-elles développées en un nombre variable d'octets? Faire u"" et u8"" les chaînes ont une sémantique de codage, par exemple Puis-je dire char16_t x[] = u"\U0010FFFF", et le point de code non BMP est codé en une séquence UTF16 à deux unités? Et de même pour u8? Dans (1), puis-je écrire des substituts isolés avec \u? Enfin, certaines des fonctions de chaîne codent-elles (c'est-à-dire qu'elles sont sensibles aux caractères et peuvent détecter des séquences d'octets invalides)?

C'est un peu une question ouverte, mais j'aimerais obtenir une image aussi complète que possible du nouveau codage UTF et des fonctionnalités de type du nouveau C++ 11.

76
Kerrek SB

Les références de caractères\x/\ u/\ U sont-elles librement combinables avec tous les types de chaînes?

Non. \x Peut être utilisé dans n'importe quoi, mais \u Et \U Ne peuvent être utilisés que dans des chaînes spécifiquement encodées en UTF. Cependant, pour toute chaîne encodée en UTF, \u Et \U Peuvent être utilisés comme bon vous semble.

Tous les types de chaînes sont-ils de largeur fixe, c'est-à-dire que les tableaux contiennent exactement autant d'éléments que ceux qui apparaissent dans le littéral, ou les références à\x/\ u/\ U sont développées en un nombre variable d'octets?

Pas comme tu l'entends. \x, \u Et \U Sont convertis en fonction du codage de la chaîne. Le nombre de ces "unités de code" (en utilisant des termes Unicode. Une valeur char16_t Est une unité de code UTF-16) dépend du codage de la chaîne contenant. Le littéral u8"\u1024" Créerait une chaîne contenant 2 chars plus un terminateur nul. Le littéral u"\u1024" Créerait une chaîne contenant 1 char16_t Plus un terminateur nul.

Le nombre d'unités de code utilisées est basé sur le codage Unicode.

Les chaînes u "" et u8 "" ont-elles une sémantique de codage, par exemple puis-je dire char16_t x [] = u "\ U0010FFFF" et le point de code non-BMP est codé en une séquence UTF16 à deux unités?

u"" Crée une chaîne codée UTF-16. u8"" Crée une chaîne codée UTF-8. Ils seront encodés selon la spécification Unicode.

Dans (1), puis-je écrire des substituts isolés avec\u?

Absolument pas. La spécification interdit expressément d'utiliser les paires de substitution UTF-16 (0xD800-0xDFFF) comme points de code pour \u Ou \U.

Enfin, certaines des fonctions de chaîne codent-elles (c'est-à-dire qu'elles sont sensibles aux caractères et peuvent détecter des séquences d'octets invalides)?

Absolument pas. Eh bien, permettez-moi de reformuler cela.

std::basic_string Ne traite pas des encodages Unicode. Ils peuvent certainement stocker des chaînes encodées en UTF. Mais ils ne peuvent les considérer que comme des séquences de char, char16_t Ou char32_t; ils ne peuvent pas les considérer comme une séquence de points de code Unicode qui sont encodés avec un mécanisme particulier. basic_string::length() renverra le nombre d'unités de code, pas de points de code. Et évidemment, les fonctions de chaîne de bibliothèque standard C sont totalement inutiles

Il convient toutefois de noter que la "longueur" d'une chaîne Unicode ne signifie pas le nombre de points de code. Certains points de code combinent des "caractères" (un nom malheureux), qui se combinent avec le point de code précédent. Ainsi, plusieurs points de code peuvent correspondre à un seul caractère visuel.

Les Iostreams peuvent en fait lire/écrire des valeurs codées Unicode. Pour ce faire, vous devrez utiliser une locale pour spécifier l'encodage et l'imprégner correctement dans les différents endroits. C'est plus facile à dire qu'à faire, et je n'ai pas de code sur moi pour vous montrer comment.

51
Nicol Bolas