Il est un peu difficile de dire par où commencer ici, car il y a beaucoup de suppositions en jeu.
Dans C comme nous le connaissons et l'aimons, il existe un type de données 'char'. Dans toutes les implémentations couramment utilisées, ce type de données contient un octet de 8 bits.
Dans le langage, contrairement à toutes les fonctions de bibliothèque que vous utilisez, ces éléments ne sont que des entiers à deux éléments. Ils n'ont aucune sémantique de «caractère». Dès que vous commencez à appeler des fonctions de la bibliothèque standard avec 'str' ou 'is' dans leurs noms (par exemple, strcmp, isalnum), vous avez affaire à la sémantique des caractères.
Les programmes C doivent faire face au désordre géant fait de la sémantique des caractères avant l'invention d'Unicode. Diverses organisations ont inventé un très grand nombre de normes d'encodage. Certains sont un caractère par octet. Certains sont plusieurs caractères par octet. Dans certains, il est toujours sûr de demander if (charvalue == 'a')
. Dans d'autres, cela peut obtenir la mauvaise réponse en raison d'une séquence multi-octets.
Dans à peu près tous les environnements modernes, la sémantique de la bibliothèque standard est déterminée par les paramètres régionaux.
Où l'UTF-8 entre-t-il? Il y a longtemps, le Consortium Unicode a été fondé pour essayer de mettre de l'ordre dans tout ce chaos. Unicode définit une valeur de caractère (dans un espace de caractère de 32 bits) pour beaucoup, beaucoup, beaucoup de caractères. L'intention est de couvrir tous les caractères d'utilisation pratique. Si vous voulez que votre code fonctionne en anglais, en arabe, en chinois et en sumérien cunéiforme, vous voulez une sémantique de caractères Unicode, pas pour écrire du code qui esquive et tisse un codage de caractères différent. Sur le plan conceptuel, la façon la plus simple d'utiliser des caractères 32 bits (UTF-32) consiste à utiliser un seul élément par caractère logique. La plupart des gens ont décidé que cela n'était pas pratique. Notez que, dans les versions modernes de gcc, le type de données wchar_t est un caractère 32 bits --- mais Microsoft Visual Studio n'est pas d'accord, définissant ce type de données à 16 bits (UTF-16 ou UCS-2, en fonction de votre point de vue).
La plupart des programmes non Windows C sont beaucoup trop investis en caractères 8 bits pour être modifiés. Ainsi, la norme Unicode inclut UTF-8, une représentation du texte Unicode comme une séquence de 8 bits. En UTF-8, chaque caractère logique a une longueur comprise entre 1 et 4 octets. Les caractères de base ISO-646 ('ascii') se jouent eux-mêmes, les opérations simples sur des caractères simples fonctionnent comme prévu. Si votre environnement inclut des paramètres régionaux pour UTF-8, vous pouvez définir les paramètres régionaux sur un environnement local UTF-8 et toutes les fonctions standard de lib fonctionneront. Si votre environnement n'inclut pas les locales pour UTF-8, vous aurez besoin d'un module complémentaire, comme ICU ou ICONV.
Cette discussion entière est restée, jusqu'à présent, aux données se reposant dans des variables dans la mémoire. Vous devez également composer avec la lecture et l'écriture. Si vous appelez open(2)
ou l'équivalent moral de Windows, vous obtiendrez les octets bruts du fichier. Si ceux-ci ne sont pas en UTF-8, vous devrez les convertir si vous voulez travailler en UTF-8.Si vous appelez fopen(3)
, la bibliothèque standard peut essayer de vous faire une faveur et effectuer une conversion entre son idée de l'encodage par défaut des fichiers et son idée de ce que vous voulez en mémoire. Si vous avez besoin, par exemple, d'exécuter un programme sur un système dans une langue grecque et de lire un fichier de chinois dans Big5, vous devrez faire attention aux options que vous passerez à ouvrir, ou vous voudrez peut-être l'éviter. Et vous aurez besoin d'ICONV ou ICU pour convertir vers et depuis UTF-8.
Votre question mentionne 'input strings'. Cela pourrait être un certain nombre de choses. Dans un environnement local UTF-8, argv
sera UTF-8. Le descripteur de fichier 0 sera UTF-8. Si le shell ne s'exécute pas dans un environnement local UTF-8 et que vous appelez le setlocale
dans un environnement local UTF-8, vous n'obtiendrez pas nécessairement les valeurs dans UTF-8 dans argv
. Si vous connectez le contenu d'un fichier à un descripteur de fichier, vous obtiendrez tout ce qui se trouve dans le fichier, quel que soit son encodage.
Les points de code UTF-8 sont compris entre 1 et 6 octets, et non entre 1 et 4, car chaque octet successif a un bit de moins. – Ioan
@loan, plus maintenant. Représenter des paires de substitution comme deux séries de trois n'est plus acceptable. – bmargulies
@bmargulies, Je ne sais pas ce que tu veux dire. Je pensais que la raison pour laquelle cela prenait 1-6 octets était parce que 8b + 7b + 6b + 5b + 4b + 3b = 33 bits pour contenir un point de code possible de 32 bits? – Ioan