IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

printf arguments variants


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Par défaut printf arguments variants
    Je récupère une version d'un code source en C ou printf était utilisé de la façon suivante :
    printf("%1$ld%2$s%6$7.7ld", 2134,(const char*) "valu", 1234, (const char*)"emet", "autreem", 1234);
    Lors d'une compilation via l'optimisation gcc "O2", j'ai le droit à un plantage du printf. Si je vire l'option, cela marche.
    J'aimerai savoir si il existe un workarround via une option du GCC ou autre permettant d'utiliser le printf comme cela. Ou bien si il existe une autre fonction que le printf permettant d'utiliser un pattern de formattage variant sans l'intégralité des arguments.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bonjour,
    C'est juste que le printf ne comprends que trois %, et qu'il y a six arguments.
    Quelque soit le compilo, ce printf est faux.
    Donner trop d'arguments est un comportement <indéfini/défini par l'implémentation>, visiblement, GCC plante dans ton cas.

    Le bon workaround, c'est de corriger le printf.

  3. #3
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    A mon avis le problème est plus sûrement du à ce que tu utilises %ld (long) alors que l'argument est un int, surtout si tu compiles en 64 bits. Utilise %d, ou passe 1234L.

    Les argument surnuméraires, évidemment ce n'est pas correct, mais je ne vois pas comment ça pourrait faire planter ton programme.

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Si le comportement n'est pas défini par la norme, alors ça peut planter sur certaines implémentations

  5. #5
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Citation Envoyé par leternel Voir le message
    Bonjour,
    C'est juste que le printf ne comprends que trois %, et qu'il y a six arguments.
    Quelque soit le compilo, ce printf est faux.
    Donner trop d'arguments est un comportement <indéfini/défini par l'implémentation>, visiblement, GCC plante dans ton cas.

    Le bon workaround, c'est de corriger le printf.
    Non, ce code n'est pas faux. Du moins, pas sur ce point.
    Jouer avec la position de l'argument qu'on utilise est très courant. Surtout dans la traduction. D'un point de vue pure C, il n'y a jamais "trop" ou "top peu" d'arguments à une fonction variadique. C'est printf lui-même qui risque de faire de la merde en essayant de lire plus d'arguments qu'il n'y en a.

    Citation Envoyé par [url=http://flash-gordon.me.uk/ansi.c.txt]Standard C89[/url] section 4.9.6.1 The fprintf function et [url=http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf]standard C99[/url] section 7.19.6.1 The fprintf function et [url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf]standard C11[/url] section 7.21.6.1 The fprintf function
    The fprintf function writes output to the stream pointed to by
    stream , under control of the string pointed to by format that
    specifies how subsequent arguments are converted for output. If there
    are insufficient arguments for the format, the behavior is undefined.
    If the format is exhausted while arguments remain, the excess
    arguments are evaluated (as always) but are otherwise ignored.
    The
    fprintf function returns when the end of the format string is
    encountered.

    Cela dit, prendre des arguments dans un ordre arbitraire ne fait pas parti du standard C. C'est par contre spécifié par POSIX. POSIX qui dit que si on utilise le format %n$ il faut que tous les arguments avant lui soient spécifiés.

    The format can contain either numbered argument conversion specifications (that is, "%n$" and "*m$"), or unnumbered argument conversion specifications (that is, % and * ), but not both. The only exception to this is that %% can be mixed with the "%n$"
    form. The results of mixing numbered and unnumbered argument specifications in a format string are undefined. When numbered argument specifications are used, specifying the Nth argument requires that all the leading arguments, from the first to the
    (N-1)th, are specified in the format string.
    En effet, sans ça il ne peut pas connaître la taille des arguments sur la pile (4 ou 8 octets en général) et ne peut donc pas atteindre l'argument demandé.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Note: Lien Single UNIX Specification

    ^Merci. L'erreur viendrait donc d'une part de la taille des arguments mal spécifiée (si long est plus long que int, comme en 64 bits sous *n*x ou en 16 bits) d'autre part de la spécification de l'argument 6 sans les autres.

    Le problème majeur quant à la seconde partie, c'est qu'il n'existe apparemment pas de spécificateur de format pour dire "invisible", ce qui aurait permis de définir le type des arguments "sautés". Ici, il n'y a que deux solutions: Afficher tout ou changer l'ordre des arguments pour que les arguments non-imprimés soient forcément les derniers.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Je suppose que ta chaîne de format n'est pas constante.
    Donc à voir si selon comment elle est construite.

    Et sinon, si tu utilises gcc avec la glibc et les bonnes options de warning (mais tout le monde met les warnings, n'est-ce pas ?), gcc devrait te dire qu'il y a un foirage dans le format.

    Citation Envoyé par gcc -Wall -Wextra
    test.printf.c: In function `main':
    test.printf.c:5:2: warning: format `%ld' expects argument of type `long int', but argument 2 has type `int' [-Wformat]
    test.printf.c:5:2: warning: format `%ld' expects argument of type `long int', but argument 7 has type `int' [-Wformat]
    test.printf.c:5:2: warning: format argument 3 unused before used argument 6 in $-style format [-Wformat]
    test.printf.c:5:2: warning: format argument 4 unused before used argument 6 in $-style format [-Wformat]
    test.printf.c:5:2: warning: format argument 5 unused before used argument 6 in $-style format [-Wformat]
    Et si je rajoute l'option -m 32, l'exécution me donne même le bon résultat.


    Sinon, tu peux dire à printf de ne pas afficher les chaînes de caractère avec le format %.0s. Mais j'ai rien trouvé pour les entiers.

Discussions similaires

  1. Passage des arguments pour printf
    Par Missa dans le forum C
    Réponses: 8
    Dernier message: 01/09/2009, 13h40
  2. Réponses: 2
    Dernier message: 16/08/2009, 00h56
  3. Réponses: 4
    Dernier message: 31/10/2008, 18h54
  4. Printf et mauvais arguments
    Par Luc Hermitte dans le forum C
    Réponses: 4
    Dernier message: 10/01/2008, 12h04
  5. Réponses: 8
    Dernier message: 29/03/2007, 11h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo