Il n'est pas clair pour moi ce que les codages sont utilisés là où en C argv. En particulier, je suis intéressé par le scénario suivant:
- Un utilisateur utilise les paramètres régionaux de L1 pour créer un fichier dont le nom, N, contient des caractères non-ASCII
- Plus tard, un utilisateur utilise les paramètres régionaux de L2 à onglet-compléter le nom du fichier sur la ligne de commande, qui est introduit dans un programme P, comme un argument de ligne de commande
Ce que la séquence d'octets ne P voir sur la ligne de commande?
J'ai observé que sur Linux, la création d'un nom de fichier en UTF-8 puis onglet-en le complétant en (par exemple) le zw_TW.big5 semble la cause de mon programme P d'être nourri UTF-8 plutôt que de Big5. Cependant, sur OS X de la même série d'actions résultats dans mon programme P l'obtention d'un Big5 codée nom de fichier.
Voici ce que je pense qui se passe jusqu'à présent (long, et je suis probablement mal et doivent être corrigées):
Windows
Les noms de fichiers sont stockés sur le disque dans certains format Unicode. Afin que Windows prend le nom de N, se convertit en L1 (la page de code) pour une version Unicode de N nous appellerons N1, et les magasins de N1 sur le disque.
Ce que je puis supposer qui se passe est que lorsque l'onglet de remplir plus tard, le nom N1 est converti à locale L2 (la nouvelle page de code) pour l'affichage. Avec de la chance, cela donnera le nom d'origine N -- mais ce ne sera pas vrai si N caractères contenus irreprésentable dans la L2. Nous appelons le nouveau nom de N2.
Lorsque l'utilisateur appuie sur entrée pour exécuter P avec cet argument, le nom de N2 est de nouveau converti en unicode, produisant N1 de nouveau. Cette N1 est maintenant disponible pour le programme en UCS2 format via GetCommandLineW/wmain/tmain, mais les utilisateurs de GetCommandLine/main verrez le nom de N2 dans les paramètres régionaux en cours (page de code).
OS X
Le disque de stockage de l'histoire est la même, autant que je sache. OS X stocke les noms de fichiers en Unicode.
Avec un terminal unicode, je pense que se passe est que le terminal construit la ligne de commande dans une Unicode tampon. Donc, lors de l'onglet complet, il copie le nom du fichier comme un fichier Unicode nom de la mémoire tampon.
Lorsque vous exécutez la commande, qui unicode tampon est converti à la locale courante, L2, et nourrir le programme via argv, et le programme peut décoder argv avec les paramètres régionaux actuels en Unicode pour l'affichage.
Linux
Sur Linux, tout est différent et je suis extra-confus au sujet de ce qui se passe. Linux stocke les noms de fichiers comme des chaînes d'octets, pas dans Unicode. Donc, si vous créez un fichier avec le nom de N dans les paramètres régionaux de L1 qui N comme une chaîne d'octets est ce qui est stocké sur le disque.
Quand je plus tard, lancez le terminal et d'essayer d'onglet-compléter le nom, je ne suis pas sûr de ce qui se passe. Il me semble que la ligne de commande est construit comme un tampon d'octets, et le nom du fichier comme une chaîne d'octets est juste concaténé à la mémoire tampon. Je suppose que lorsque vous tapez un caractère standard il est codé à la volée d'octets qui sont ajoutés à la mémoire tampon.
Lorsque vous exécutez un programme, je pense que la mémoire tampon est envoyé directement à argv. Maintenant, ce que le codage ne argv ont? Il ressemble à tous les caractères que vous avez tapé dans la ligne de commande alors que dans les paramètres régionaux de L2 sera en L2 l'encodage, mais le nom de fichier dans la L1 de l'encodage. Donc, argv contient un mélange de deux codages!
Question
J'aimerais vraiment que quelqu'un pourrait me permettre de savoir ce qui se passe ici. Tout ce que j'ai en ce moment est à moitié suppositions et de la spéculation, et il n'a pas vraiment d'ajustement ensemble. Ce que j'aimerais vraiment être vrai, c'est pour argv encodé dans la page de code (Windows) ou les paramètres régionaux actuels (Linux / OS X), mais qui ne semble pas être le cas...
Extras
Voici un simple candidat programme P qui vous permet d'observer les codages pour vous-même:
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Not enough arguments\n");
return 1;
}
int len = 0;
for (char *c = argv[1]; *c; c++, len++) {
printf("%d ", (int)(*c));
}
printf("\nLength: %d\n", len);
return 0;
}
Vous pouvez utiliser locale -a
voir les locales disponibles, et d'utiliser export LC_ALL=my_encoding
modifier vos paramètres régionaux.