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 :

Fonctions avec listes variables d'arguments


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de loupapet
    Homme Profil pro
    Retraité d'Eurocopter
    Inscrit en
    Janvier 2009
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité d'Eurocopter
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 69
    Par défaut Fonctions avec listes variables d'arguments
    Bonjour à tous,

    Je reviens sur le site pour solliciter les éclairages de développeurs en C. J'ai cherché en vain la possibilité du propager une liste variable d'arguments d'une fonction vers une autre.

    Soit la suite des deux instructions suivantes fréquemment utilisées comme telles dans une mise en page :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sprintf (zone , "x=%d - y=%d - z=%d" , x , y , z) ;
    iret = fonction_A (a , b , c , attribut , zone) ;
    Il serait souhaitable, pour simplifier le travail du programmeur, de proposer directement un appel à une fonction plus élaborée comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    iret = fonction_B( a , b , c , attribut ,  "x=%d - y=%d - z=%d", x , y , z) ;
    Dans le passé, j'ai eu, une ou deux fois, l'occasion d'utiliser les listes variables d'arguments. Je pensais que, dans le cas présent, le problème était beaucoup plus simple puisque l'analyse du format était refilée à la fonction standard "sprintf". J'ai donc écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int fonction_B( a , b , c , attribut , format , va_alist)
    int                a, b, c     ;
    char               attribut[] ;
    char               format[]   ;
    {
      char     zone[256] ;
      va_list ap ;
     
      va_start(ap , format) ;                             // liste variable après 'format'
      sprintf (zone, format, ap ) ;
      va_end(ap) ;
     
      return (fonction_A( a , b , c , attribut , zone) ) ;
    }
    La compilation et l'édition de liens se passent très bien mais l'exécution, sans erreur, n'est pas bonne.

    Très sincèrement, je ne vois pas où je fais des erreurs. J'ai probablement mal interprété la documentation que j'ai pu glaner ça et là sur la Toile.

    Je suis sous MinGW/Msys Windows. À son installation, MinGW n'avait pas incorporé le fichier d'entête "stdarg.h". J'en ai téléchargé plusieurs. Le seul qui ne provoque pas d'erreur à la compilation est celui ci-dessous :
    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
    #ifndef __STDARG_H
    #define __STDARG_H
     
    typedef void *va_list;
     
    #define __size(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int)-1))
     
    #define va_start(ap, parmN) ((void)((ap) = (va_list)((char *)(&parmN)+__size(parmN))))
     
    #define va_arg(ap, type) (*(type *)(((*(char **)&(ap))+=__size(type))-(__size(type))))
    #define va_end(ap)          ((void)0)
     
    #if !__STDC__
    #define _va_ptr             (...)
    #endif
     
    #endif
    La forme "int fonction_B( a , b , c , attribut , format , ...)" provoque une erreur à la compilation !...

    Avez-vous une idée ?

    Merci d'avance.
    Cordialement.
    Lou Papet

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Attention, cela fait un certain temps que l'on ne définit plus une fonction comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int fonction_B( a , b , c , attribut , format , va_alist)
    int                a, b, c     ;
    char               attribut[] ;
    char               format[]   ;
    { ...
    Les compilateurs d'après 1998 devrait la refuser!

    Pour l'utilisation de stdarg.h, il ne faut pas en chercher quelque part, il faut impérativement utiliser celui qui est livré avec le compilateur (car les données sont directement liées à la manière utilisées par le compilateur pour mettre les données dans la pile.) Attention stdarg.h est un tout nouveau fichier (il est sorti en 1990), avant il y en avait un autre qui s'appelait varargs.h.

    sprintf() est une fonction qui attend un nombre variable d'arguments, elle n'attend pas un va_list! Pour résoudre ton problème, il faudrait utiliser une fonction qui s'attend à recevoir un va_list.
    ...
    Heureusement cette fonction existe bien (depuis 1999), elle s'appelle vsprintf().

  3. #3
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 783
    Par défaut
    Hello,

    Si tu veux propager un liste variable d'arguments, voici une manière de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdarg.h>
     
    void fct(type arg1,type arg2,const char *format,...) {
        va_list args;
     
        // do something with arg1 and arg2
        ....
        va_start(args,format);
        fct_with_va(format,args);        // call function with variable list of args given by caller
        va_end(args);
        ....
    }

  4. #4
    Membre confirmé Avatar de loupapet
    Homme Profil pro
    Retraité d'Eurocopter
    Inscrit en
    Janvier 2009
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité d'Eurocopter
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 69
    Par défaut Il y a un tout petit progrès !....
    Bonjour,

    Citation Envoyé par edgarjacobs Voir le message
    Hello,

    Si tu veux propager un liste variable d'arguments, voici une manière de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdarg.h>
     
    void fct(type arg1,type arg2,const char *format,...) {
        va_list args;
     
        // do something with arg1 and arg2
        ....
        va_start(args,format);
        fct_with_va(format,args);        // call function with variable list of args given by caller
        va_end(args);
        ....
    }
    J'ai téléchargé un autre fichier entête "stdarg.h". Maintenant, à la compile, la forme (...) ne provoque plus d'erreur et peut donc remplacer l'ancienne forme (va_alist).
    En dehors de cela, ce que vous me proposez est identique à ce que j'ai écrit.

    J'ai bien ajouté "const" mais cela n'a rien changé. L'argument "format" est bien à passer à la fonction "sprintf". La procédure doit savoir que c'est un "char*" que "sprintf" va analyser pour connaître les différents types d'arguments. Le nouveau prototype est celui_ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int fonction_B( int a, int b, int c, char *attribut, const char *format  , ...)
    {
      char     zone[256] ;
      va_list ap ;
     
      va_start(ap, format) ;                             // liste variable après 'format' y compris
      sprintf (zone, ap ) ;
      va_end(ap) ;
     
      return (fonction_A( a , b , c , attribut , zone) ) ;
    }
    pour un appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    iret = fonction_B( a , b , c , attribut ,  "x=%d - y=%d - z=%d", x , y , z) ;
    Malheureusement, le résultat n'est guère plus fructueux ... la fonction me sort des hiéroglyphes !...

    Mais en cherchant encore un petit peu, on va peut-être y arriver !... Mais où est-ce que cela coince ????....

    Pour mieux comprendre sous gdb, j'essaie d'écrire une petite fonction pour simuler 'sprintf' mais ça n'a pas l'air bien brillant pour le moment !...

    Merci
    Lou Papet

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Genre ce truc compile..

    Tu as réussi à passer outre tous les conseils de dalfab. Relis son post - tout y est - et recommence.

  6. #6
    Membre confirmé Avatar de loupapet
    Homme Profil pro
    Retraité d'Eurocopter
    Inscrit en
    Janvier 2009
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité d'Eurocopter
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 69
    Par défaut Non, bien au contraire !...
    Bonsoir Matt_Houston,

    Non, pas du tout. J'avais suivi ses conseils. Mais c'était avant que je retélécharge le dernier fichier entête 'stdarg.h" qui a d'ailleurs étrangement ressemblé au premier. Peut-être une erreur de téléchargement. Je n'ai pas trouvé pourquoi.
    Eh oui !... l'installation du MinGW ne fournit pas ce fichier à partir du fichier d'installation "mingw-get-setup.exe". C'est la version "0.6.2 beta-20131004-1". J'ai regardé s'il y avait une version plus récente. Je suis toujours retombé sur la même.

    Devant cette absence, je pense qu'il faut essayer d'agir, et tenter des solutions. Mais après avoir envoyé mon message à 18h 04, je suis revenu sur la proposition 'vsprintf()" fournie par dalfab et ça a marché. J'ai quand même tilté sur son info.

    Votre message a anticipé ma réponse définitive. Pas assez rapide.... l'âge peut-être !....

    Je marque donc le sujet comme résolu en vous remerciant beaucoup à tous.
    Bien cordialement.
    Lou Papet.

  7. #7
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par dalfab Voir le message
    [..]Les compilateurs d'après 1998 devrait la refuser!
    Non : j'ai compilé la zlib qui en contenait (avec vs2015, vs2017 & CLANG), sans aucun problème.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/01/2013, 11h01
  2. Réponses: 2
    Dernier message: 16/10/2007, 10h53
  3. Réponses: 3
    Dernier message: 23/08/2007, 00h39
  4. Fonction avec parametre variable
    Par Linaa dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 17/12/2006, 12h41
  5. Réponses: 1
    Dernier message: 20/07/2005, 09h13

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