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 :

Comment fait va_arg() pour prend 2ième paramètre un type de donnée


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 5
    Points : 5
    Points
    5
    Par défaut Comment fait va_arg() pour prend 2ième paramètre un type de donnée
    Pour résoudre un problème je voulais m'inspirer de la fonction va_arg, car elle prend un type de donnée comme second argument, j'aimerai pouvoir faire la même chose. En cherchant j'ai trouvé que va_arg était une macro definie dans stdarg.h :
    #define va_arg(v,l) __builtin_va_arg(v,l)
    mais je ne trouve pas le prototype de __builtin_va_arg() je ne comprend pas quel peut être le type de donnée du second argument.
    Je sais que certaines fonctions utilisent une marco du style :
    #define ma_fonction_void(x,y) ma_fonction_ ## y(x)
    ce qui permet d'écrire :
    ma_fonction_void( 1000, long)
    qui sera converti en par le préprocesseur en
    ma_fonction_long( 1000)
    évidement cela impose d'écrire autant de fonctions qu'il y a de types, et cela sera toujours insuffisant car on ne peut pas prévoir pour les types «*enum*» ou «*struct*» définit postérieurement par un autre utilisateur qui utilisera cette fonction.

  2. #2
    Membre actif
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 487
    Points : 294
    Points
    294
    Par défaut
    voici un petit example de va_arg
    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
    19
    20
    #include <stdio.h>
    #include <stdarg.h>
     
    void sum(char *msg, ...)
    {
       int total = 0;
       va_list ap;
       int arg;
       va_start(ap, msg);
       while ((arg = va_arg(ap,int)) != 0) {
          total += arg;
       }
       printf(msg, total);
       va_end(ap);
    }
     
    int main(void) {
       sum("The total of 1+2+3+4 is %d\n", 1,2,3,4,0);
       return 0;
    }

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Merci mais ce n'était pas vraiment la question. La question n'est pas comment utilisé va_arg, mais comment fait va_arg pour accepter un type de donnée en second argument.
    Par exemple je veux faire une fonction qui prend 2 arguments ; le 1ier est le type de donnée le 2ième est la valeur :
    ma_fonction( int, 25);
    ma fonction ( char, 'f');
    ma_fonction( float, 2.5);

    Quelle est le prototype de ma_fonction ?

    Une façon de faire est d'utiliser un pointeur de type void pour la valeur et un pointeur chaîne de caractère pour le format :
    int x = 25;
    void *p = &x;
    ma_fonction( "int", p);
    et le prototype de ma_fonction sera :
    void ma_fonction( char *, void *)

    Mais j'aimerai bien pouvoir faire comme dans le premier exemple, ce qu'il est peut être possible de faire puisque c'est ce que l'on fait avec va_arg. Donc je souhaite comprendre comment marche va_arg

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut

    Citation Envoyé par sahilber
    Pour résoudre un problème je voulais m'inspirer de la fonction va_arg, car elle prend un type de donnée comme second argument, j'aimerai pouvoir faire la même chose.
    va_arg n'est pas une fonction mais une macro, c'est très important. On ne pourra jamais faire ce que fait va_arg à l'aide d'une fonction.
    Citation Envoyé par sahilber
    En cherchant j'ai trouvé que va_arg était une macro definie dans stdarg.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define va_arg(v,l) __builtin_va_arg(v,l)
    Non, elle est définie ainsi par ton compilateur.
    Citation Envoyé par sahilber
    Je ne comprend pas quel peut être le type de donnée du second argument.
    Les marcos permettent d'effectuer des substitutions avant la compilation, qui a parlé de type ? Soit par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define POINTEUR(T) T *
    Alors la ligne suivante :Sera remplacée avant la compilation (c'est-à-dire pendant la phase de précompilation) par :En ce qui concerne va_arg, elle prend la taille du type spécifié en deuxième argument pour connaître l'emplacement du paramètre suivant. Autrement dit, va_arg met le deuxième argument dans un sizeof pour ensuite faire des calculs dessus.

    Tout cela répond également, je le pense, à ton deuxième post.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Il est exacte de va_arg n'est pas toujours défini de la même façon j'ai aussi trouvé ces définitions qui correspondent à ta définition : (presque)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define va_arg(list, mode) ((mode*)(list += sizeof(mode)))[-1] 
     
    #define va_arg(ap,type) (*((type *)(ap))++)
     
    #define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3)))
    Est ce que tu suggères que __builtin_va_arg(v,l) n'est pas une véritable fonction mais plutôt un opérateur comme l'est sizeof ?

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Ca ne peut être une fonction. C'est soit une macro, soit un opérateur. D'après ce que son nom l'indique (builtin ...), il s'agit d'un opérateur au même titre que sizeof comme tu l'as dit.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/10/2008, 12h10
  2. Réponses: 9
    Dernier message: 11/04/2007, 10h56
  3. [Configuration] Comment faites-vous pour séparer les paramètres offline/online
    Par robichou dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 20/02/2007, 02h51
  4. [Struts]comment faites-vous pour enregistrer..
    Par pouss dans le forum Struts 1
    Réponses: 7
    Dernier message: 30/09/2005, 12h55
  5. Réponses: 6
    Dernier message: 08/04/2005, 03h00

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