Changer l'encodage des chaînes de caractères en C

L'encodage des chaînes de caractères peut-il être différent de l'encodage du fichier de code ?

Le problème exposé dans ce sujet a été résolu.

Bonjour,

eh oui c’est encore moi :)

Je reviens vers vous pour une question sur l’encodage des chaînes de caractères et plus largement sur la gestion des encodages par le compilateur.

Je code dans un fichier texte encodé en utf-8, ce qui signifie que, le code que va lire mon compilateur, c’est de l’utf-8. Je n’ai jamais eu besoin de paramétrer mon compilateur pour qu’il lise bien cet encodage pour mon code, d’où ma première question : peut-on régler l’encodage des fichiers de code avec un option de compilation particulière ? J’imagine que oui, mais j’en doute quand même car, étant donné que tous les caractères qu’on utilise pour du code tiennent dans de l’ascii de base, je ne serais pas surpris que les compilateurs ne soient conçus que pour lire de l’ascii (l’utf-8 étant, pour des caractères ascii, équivalant !).

Maintenant, concernant les chaînes de caractères littérales, j’ai vu dans le tutoriel du cours qu’on pouvait ajouter l’option u8 devant une chaîne (exemple : char chaine[] = u8"coucou";) pour forcer le compilateur à l’encoder en utf-8. Si le compilateur ne lit que du code en utf-8 cette option serait sans aucun intérêt (ne compilateur n’aurait besoin de faire aucune conversion). Mais la présentation de cette option dans le cours me paraît alors complètement inutile puisque la question des différents encodages pris en charge par le compilateur n’est pas abordée… Pour me faire bien comprendre : à mon avis, soit on considère que le compilateur lit forcément de l’utf-8 et le préfixe u8 est sans intérêt, soit on considère que le compilateur peut lire différents encodages de texte et il faut en parler avant d’introduire l’option u8. Je ne trouve pas sur internet des gens qui auraient été confrontés à ce pb, de changer l’encodage du code lu par le compilateur (ce qui est compréhensible, cela n’a pas grand intérêt de faire ça hormis pour la curiosité).

De même pour la conversion en caractères larges, le préfixe L sert à indiquer vers quoi on souhaite convertir, mais à aucun moment on ne parle de quel encodage source on part.

Merci pour votre aide !

Salut,

Concernant tes questions je me demande si c’est vraiment du ressort du compilateur.

Je ne serais pas étonné que celui-ci ne traite que des octets (pas de l’ascii, des octets bruts) et que ce soit donc ton éditeur de texte qui détermine l’encodage utilisé dans les chaînes de caractères qui figurent dans le fichier (mais ce n’est qu’une supposition, y a peut-être quand même une gestion des encodages pour apporter une couche de compatibilité).

Edit : ça a l’air confirmé par mes tests locaux avec un programme qui imprime juste une chaîne stockée en dur. Un fichier source encodé en UTF-8 donne une sortie UTF-8, tandis qu’un fichier source en latin-1 donne une sortie latin-1.

peut-on régler l’encodage des fichiers de code avec un option de compilation particulière ?

C’est du ressort du compilateur ça. La norme C ne s’occupe pas de ce genre de chose. En fonction de ton compilateur et de la version, l’option n’est pas là même. C’est relativement récent comme option du coté de gcc.

Bref, l’option est -finput-charset: https://gcc.gnu.org/onlinedocs/cpp/Character-sets.html

@entwanne: Ton test s’explique car GCC compile de l’UTF8 par défaut, et il ne se soucis pas de si c’est de l’UTF8 valide. Et comme il est sensé sortir de l’UTF8 aussi … Il fait effectivement juste traité ça au niveau octet (tu lui dis que c’est de l’UTF8, il doit sortir de l’UTF8, franchement, je comprend pour le coup). Par-contre, si tu compiles de l’UTF8 et que tu précises l’option, il fait bien la conversion.

+1 -0

Tout dépend du langage de programmation.
Si ce langage est prévu pour pouvoir manipuler de l’utf8, il faut pouvoir définir des chaînes de caractères représentés en utf8.
En particulier, utf8 permet d’encoder les caractères UNICODE, mais il y a d’autres façons de le faire (utf16, utf32 avec les variantes LE et BE).
Les caractères du jeu ASCII sont de longueur constante : 1 octet.
Mais on peut représenter d’autres jeux de caractères sur 1 octet, par exemple le jeu latin-1 avec des lettres accentuées.
Les caractères encodés en utf8 sont de longueur variable : entre 1 et 4 octets.

De ce fait, c’est très facile de connaître la longueur d’une chaîne ASCCI, alors que c’est bien plus compliqué pour une chaîne utf8.
C’est pourquoi certains langage exigent qu’on déclare les chaînes encodées en utf8, les autres chaîne étant supposées avoir un caractère par octet : le compilateur peut alors traiter les chaînes de manière optimisée.

+1 -0

Salut,

Je code dans un fichier texte encodé en utf-8, ce qui signifie que, le code que va lire mon compilateur, c’est de l’utf-8. Je n’ai jamais eu besoin de paramétrer mon compilateur pour qu’il lise bien cet encodage pour mon code, d’où ma première question : peut-on régler l’encodage des fichiers de code avec un option de compilation particulière ?

AScriabine

Comme l’a dit @ache, avec GCC, oui, via l’option -finput-charset, mais ce n’est pas le cas de tous les compilateurs.

J’imagine que oui, mais j’en doute quand même car, étant donné que tous les caractères qu’on utilise pour du code tiennent dans de l’ascii de base, je ne serais pas surpris que les compilateurs ne soient conçus que pour lire de l’ascii (l’utf-8 étant, pour des caractères ascii, équivalant !).

AScriabine

Ce serait assez gênant si c’était le cas puisque par exemple ils seraient incapables de convertir des chaînes de caractère littérales vers leur équivalent large ou d’encoder directement une chaîne littérale en UTF-8.

Maintenant, concernant les chaînes de caractères littérales, j’ai vu dans le tutoriel du cours qu’on pouvait ajouter l’option u8 devant une chaîne (exemple : char chaine[] = u8"coucou";) pour forcer le compilateur à l’encoder en utf-8. Si le compilateur ne lit que du code en utf-8 cette option serait sans aucun intérêt (ne compilateur n’aurait besoin de faire aucune conversion). Mais la présentation de cette option dans le cours me paraît alors complètement inutile puisque la question des différents encodages pris en charge par le compilateur n’est pas abordée… Pour me faire bien comprendre : à mon avis, soit on considère que le compilateur lit forcément de l’utf-8 et le préfixe u8 est sans intérêt, soit on considère que le compilateur peut lire différents encodages de texte et il faut en parler avant d’introduire l’option u8. Je ne trouve pas sur internet des gens qui auraient été confrontés à ce pb, de changer l’encodage du code lu par le compilateur (ce qui est compréhensible, cela n’a pas grand intérêt de faire ça hormis pour la curiosité).

AScriabine

Attention à différencier l’encodage pour écrire la chaîne littérale (celui utilisé pour écrire le fichier source) et l’encodage finale de la chaîne littérale, au sein de l’exécutable, qui dépend du compilateur. C’est tout le sens et la différence entre l’option -finput-charset=utf-8 qui dit « les fichiers sources sont en l’UTF-8 » et l’option -fexec-charset=utf-8 qui dit « les chaîne littérales sont encodées en UTF-8 ». Le préfixe u8 passe outre la dernière option et force l’encodage d’une chaîne littérale en UTF-8.

+1 -0

Le titre du sujet désigne le langage C :

Changer l’encodage des chaînes de caractères en C

De même qu’il possède le tag C. Du coup, là, nous on parle du langage C spécifiquement.

+2 -0

Bonjour,

Je ne comprends pas la réponse de Etherpin:

Les caractères encodés en utf8 sont de longueur variable : entre 1 et 4 octets.

etherpin

Sauf erreur de ma part:

  • Un char: C’est 8 bits. Un UTF8: c’est un unsigned char, avec les valeurs de 0 à 127 étant les ASCII, et de 128 à 256 "D’autres caractères" (en fonction du codage choisi).

  • Maintenant, si on travaille en Unicode, un caractère, c’est un UTF16 (ou un UTF32, je viens de découvrir …), mais c’est plus un UTF8.

Il y a quelque chose que je n’ai pas compris ?

Merci pour vos explications.

En UTF-8, plusieurs caractères (au sens char) peuvent n’encodé un seul caractère (au sens point de code, donc relatif au charset).

En Unicode, il faut distingué, le point de code et l’encodage utilisé pour représenter ce point de code. Oui, c’est compliqué. UTF-8 et UTF-32 représente le même char-set mais pas de la même manière (32bit = 1 caractère en UTF-32 alors qu’en UTF-8, un caractère va de 8 à 32bit).

L’avantage de l’UTF-8 et les langages utilisant l’alphabet latin sont codés de manière plus condensé (on gagne donc en taille) et c’est rétro-compatible avec l’ASCII, ce qui est quand même vachement pratique.

+0 -0

Bonjour,

Je ne comprends pas la réponse de Etherpin:

Les caractères encodés en utf8 sont de longueur variable : entre 1 et 4 octets.

etherpin

Sauf erreur de ma part:

  • Un char: C’est 8 bits. Un UTF8: c’est un unsigned char, avec les valeurs de 0 à 127 étant les ASCII, et de 128 à 256 "D’autres caractères" (en fonction du codage choisi).

  • Maintenant, si on travaille en Unicode, un caractère, c’est un UTF16 (ou un UTF32, je viens de découvrir …), mais c’est plus un UTF8.

Il y a quelque chose que je n’ai pas compris ?

Merci pour vos explications.

Dedeun

Ta première phrase est correcte.
Mais ta deuxième phrase ne l’est pas. En effet, utf-16 n’est pas obligatoire pour représenter les code-point d’UNICODE.On peut les représenter en utf-8, utf-16, voire utf-32.

Ma phrase n’est pas très claire. je reformule :

En utf8, les caractères du jeu ASCII sont encodés avec un octet.
Les autres caractères sont encodés avec plusieurs octets (de 2 à 4).

En fait, les caractères les plus courants utilisent 1 ou 2 octets en UTRF-8.
Certains systèmes utilisent systématiquement (et uniquement) 2 octets, par exemple Windows. Ces systèmes utilisent utf-16. Du coup, il leur faut 2 octets pour représenter les caractères du jeu ASCII.
======================edit======================
… par exemple Windows 7.
voir https://stackoverflow.com/questions/66072117/why-does-windows-use-utf-16le

+0 -0

Certains systèmes utilisent systématiquement (et uniquement) 2 octets, par exemple Windows. Ces systèmes utilisent utf-16. Du coup, il leur faut 2 octets pour représenter les caractères du jeu ASCII.

Ah ? Je savais pas ! Tu as de la documentation dessus ? Qu’est-ce qui au juste utilise UTF-8 ? Genre l’interface, explorer et tout ça ?

+0 -0

Certains systèmes utilisent systématiquement (et uniquement) 2 octets, par exemple Windows. Ces systèmes utilisent utf-16. Du coup, il leur faut 2 octets pour représenter les caractères du jeu ASCII.

Ah ? Je savais pas ! Tu as de la documentation dessus ? Qu’est-ce qui au juste utilise UTF-8 ? Genre l’interface, explorer et tout ça ?

ache

On s’éloigne du sujet. Rapidement :
J’ai lu cela en farfouillant autour d’utf-8 et d’unicode. Je l’ai constaté de visu en examinant des binaires de programmes qui ont des interfaces en français : on peu voir que les chaînes de caractères utilisées sont en utf-16.

image.png
image.png

Image de l’utilitaire A43. J’ai créé un fichier avec notepad, enregistré en "unicode". Le fichier contient la chaîne "essai".

Autre exemple, issu de charmap.exe :

image.png
image.png
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte