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

Bibliothèque standard C Discussion :

ellipse : Passage d'arguments multiples (stdarg)


Sujet :

Bibliothèque standard C

  1. #1
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut ellipse : Passage d'arguments multiples (stdarg)
    Bonjour,

    Je cherche, tout simplement, à faire une fonction acceptant un nombre multiple d'arguments.
    Je travaille sur Linux avec gcc.

    Je viens de faire le "test case" suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
     
    static void many_args(const char *string, ...) {
    	va_list args;
    	va_start(args, string);
    	while (string) {
    		puts(string);
    		string = va_arg(args, const char*);
    	}
    	va_end(args);
    }
     
    int main(void) {
    	many_args("aaa", "bbb", "ccc");
    	return EXIT_SUCCESS;
    }
    que je compile avec la ligne de commande suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -Wall -pedantic -o test test.c
    La compilation est ok, mais voilà le résultat obtenu :

    $ ./test
    aaa
    bbb
    ccc
    AWAVI��AUATL�%� 
    
    
    AWAVI��AUATL�%� 
    ����
    Erreur de segmentation (core dumped)
    $
    Je ne comprends pas !

    Est ce que quelqu'un peut m'expliquer svp ?
    Merci.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 674
    Points : 10 686
    Points
    10 686
    Par défaut
    Je dirais que ton problème est trivial

    Tu retires les arguments sur la pile - Mais quelle est la condition de fin ?
    Ce que tu observes c'est un débordement, justement parce que tu n'as pas de condition de fin.

    Il faut passer le nombre d'arguments -> void many_args(size_t nb_args, const char *string, ...).
    Ou alors peut-être terminer avec une valeur sentinelle à réfléchir.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 129
    Points : 33 061
    Points
    33 061
    Billets dans le blog
    4
    Par défaut
    va_arg ne sait pas compter les paramètres, ni déterminer leurs types.
    Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list). The function should be designed in such a way that the number of parameters can be inferred in some way by the values of either the named parameters or the additional arguments already read.
    Classiquement tu dois terminer avec une valeur sentinelle, type NULL.

    Tu as des tricks pour compter les paramètres https://renenyffenegger.ch/notes/dev...ount-arguments mais ça reste bancal.
    Le plus simple serait de passer par une macro pour l'appel réel, macro qui ajoute la sentinelle automatiquement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define many_args(...) many_args_impl(__VA_ARGS__, NULL)
    Note qu'en C++ il est possible de compter les paramètres variadiques et de déterminer leurs types.

  4. #4
    Membre habitué Avatar de domiq44
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 301
    Points : 135
    Points
    135
    Par défaut
    Citation Envoyé par foetus Voir le message
    terminer avec une valeur sentinelle
    Merci foetus, je me doutais bien de quelque chose comme ça, mais je ne me souvenais plus de cette particularité.

    Citation Envoyé par Bousk Voir le message
    Classiquement tu dois terminer avec une valeur sentinelle, type NULL.
    Merci Bousk pour toutes ces précisions.

    Voici donc le code corrigé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
     
    static void many_args(const char *string, ...) {
    	va_list args;
    	va_start(args, string);
    	while (string) {
    		puts(string);
    		string = va_arg(args, const char*);
    	}
    	va_end(args);
    }
     
    int main(void) {
    	many_args("aaa", "bbb", "ccc", NULL);
    	return EXIT_SUCCESS;
    }
    Donnant le bon résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ ./test
    aaa
    bbb
    ccc
    $

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 20/04/2010, 14h07
  2. ellipse : Passage d'arguments multiples (stdarg)
    Par domiq44 dans le forum Autres éditeurs
    Réponses: 7
    Dernier message: 04/02/2010, 15h06
  3. [TASM] Passage d'argument à une macro
    Par sorry60 dans le forum Assembleur
    Réponses: 13
    Dernier message: 23/04/2005, 18h22
  4. [web] passage d'arguments à un CGI
    Par ma2th dans le forum Web
    Réponses: 4
    Dernier message: 20/08/2004, 12h18
  5. passage d'argument à la procédure main ()
    Par Zazeglu dans le forum C
    Réponses: 5
    Dernier message: 01/09/2003, 19h59

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