Bonjour.
J'essaie de comprendre le fonctionnement des macros va_start, va_arg et va_end, utilisées pour faire des fonctions dont le nombre de paramètres est variable.
On a:
et
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define va_end(ap) ( ap = (va_list)0 )
Si je comprend l'idée:
Code : Sélectionner tout - Visualiser dans une fenêtre à part typedef char * va_list;
1/ On initialise un pointeur "ap" (char* ap), vers le premier argument "inconnu" de la fonction, avec va_start.
2/ Ensuite, on parcourt les arguments en faisant "avancer le pointeur dans la pile" en bouclant va_arg
3/ quand on a fini, on fait un p'tit va_end, juste pour remettre le pointeur à NULL. C'est plus propre.
Mais il y a certaines choses que je ne comprend pas:
A. La macro _INTSIZEOF. A quoi sert-elle?
J'ai testé:
Est-ce que c'est la taille que prend un argument passé en paramètre (posé sur la pile)?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 int intsizeof; char c; int i; double d; intsizeof = _INTSIZEOF(c); // <-- on obtient 4 intsizeof = _INTSIZEOF(i); // <-- on obtient 4 intsizeof = _INTSIZEOF(d); // <-- on obtient 8
B. Si c'est ça, je comprend bien la macro va_start(ap,v) (on fait pointer ap, derrière v, donc à "l'adresse de v + taille de v sur la pile", mais pas la macro va_arg(ap,t)?
Pour moi, ça suffirait de faire:
(on retourne un élément de type t, pointé par ap, puis on incrémente ap de la taille de cet élément.
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) )
C. Enfin, last but not least, dans les exemple que je trouve, la fonction s'attend à trouver un élément "marqueur de fin". (par exemple, la fonction fait une somme d'entier, en bouclant va_arg jusqu'à trouver un paramètre qui vaut 0, ou -1 p.ex)
Existe-t'il un moyen de faire autrement que de définir un marqueur de fin?
Merci de votre aide,
Biosox
Partager