web-dev-qa-db-fra.com

printf, wprintf,% s,% S,% ls, char * et wchar *: erreurs non annoncées par un avertissement du compilateur?

J'ai essayé le code suivant:

wprintf(L"1 %s\n","some string"); //Good
wprintf(L"2 %s\n",L"some string"); //Not good -> print only first character of the string
printf("3 %s\n","some string"); //Good
//printf("4 %s\n",L"some string"); //Doesn't compile
printf("\n");
wprintf(L"1 %S\n","some string"); //Not good -> print some funny stuff
wprintf(L"2 %S\n",L"some string"); //Good
//printf("3 %S\n","some string"); //Doesn't compile
printf("4 %S\n",L"some string");  //Good

Et j'obtiens la sortie suivante:

1 some string
2 s
3 some string

1 g1 %s

2 some string
4 some string

Donc: il semble que wprintf et printf soient capables d'imprimer correctement à la fois un char * et un wchar *, mais seulement si le spécificateur exact est utilisé. Si le mauvais spécificateur est utilisé, vous pourriez ne pas obtenir d'erreur de compilation (ni d'avertissement!) Et vous retrouver avec un mauvais comportement. Avez-vous le même comportement?

Remarque: Cela a été testé sous Windows, compilé avec MinGW et g ++ 4.7.2 (je vérifierai gcc plus tard)

Edit: j'ai aussi essayé% ls (le résultat est dans les commentaires)

printf("\n");
wprintf(L"1 %ls\n","some string"); //Not good -> print funny stuff
wprintf(L"2 %ls\n",L"some string"); //Good
// printf("3 %ls\n","some string"); //Doesn't compile
printf("4 %ls\n",L"some string");  //Good
21
Antonio

Je soupçonne que GCC (mingw) a un code personnalisé pour désactiver les vérifications des larges fonctions printf sous Windows. En effet, la propre implémentation de Microsoft (MSVCRT) est gravement erronée et a %s et %lsen arrière pour les fonctions larges printf; étant donné que GCC ne peut pas être sûr de savoir si vous établirez une liaison avec l'implémentation défectueuse de MS ou une version corrigée, la chose la moins gênante qu'il puisse faire est simplement de fermer l'avertissement.

23
R..

Les spécificateurs de format sont importants: "% s" indique que la chaîne suivante est une chaîne étroite ("ascii" et généralement 8 bits par caractère). "% S" signifie une chaîne de caractères large. Le mélange des deux donnera un "comportement indéfini", qui comprend l'impression des ordures, un seul caractère ou rien.

Un caractère est imprimé car les caractères larges font, par exemple, 16 bits de large, et le premier octet est différent de zéro, suivi d'un octet zéro -> fin de chaîne dans des chaînes étroites. Cela dépend de l'ordre des octets, dans une machine "big endian", vous n'obtiendrez aucune chaîne du tout, car le premier octet est zéro et l'octet suivant contient une valeur non nulle.

17
Mats Petersson

Au moins dans Visual C++: printf (et d'autres fonctions ACSII):% s représente une chaîne ASCII% S est une chaîne Unicode wprintf (et d'autres fonctions Unicode):% s est une chaîne Unicode% S est une chaîne ASCII

Dans la mesure où aucun avertissement du compilateur, printf utilise une liste d'arguments variables, seul le premier argument pouvant être vérifié par type. Le compilateur n'est pas conçu pour analyser la chaîne de format et vérifier les paramètres qui correspondent. Dans le cas de fonctions comme printf, cela dépend du programmeur

4
Steve R

Pour s: Lorsqu'il est utilisé avec les fonctions printf, spécifie une chaîne de caractères à un octet ou à plusieurs octets; lorsqu'il est utilisé avec les fonctions wprintf, spécifie une chaîne de caractères larges. Les caractères sont affichés jusqu'au premier caractère nul ou jusqu'à ce que la valeur de précision soit atteinte.

Pour S: Lorsqu'il est utilisé avec les fonctions printf, spécifie une chaîne de caractères larges; lorsqu'il est utilisé avec les fonctions wprintf, spécifie une chaîne de caractères à un octet ou à plusieurs octets. Les caractères sont affichés jusqu'au premier caractère nul ou jusqu'à ce que la valeur de précision soit atteinte.

Dans la plate-forme de type Unix, s et S ont la même signification que la plate-forme Windows.

Référence: https://msdn.Microsoft.com/en-us/library/hf4y5e3w.aspx

3
user3581075

%S semble conforme à La spécification Unix unique v2 et fait également partie de la version actuelle (2008) Spécification POSIX .

Les spécificateurs de format conformes C99 équivalents seraient %s et %ls.

0
David Foerster