Que se passe-t-il en interne lorsqu'une fonction qui utilise des varargs est appelée ? Les arguments eux-mêmes sont-ils stockés sur le tas ou sur la pile comme tout autre argument ? S'ils sont sur la pile, comment cela fonctionne-t-il ?
Réponses
Trop de publicités?Cela dépend de la mise en œuvre. Mais très probablement, les args sont placés sur la pile, l'un après l'autre (après que les promotions d'arguments par défaut aient été effectuées).
va_start
, va_arg
etc. fonctionnent en promenant simplement un pointeur dans la pile, et en réinterprétant les bits comme le type que vous demandez.
Comme on l'a déjà noté, cela dépend de l'implémentation.
Dans la convention d'appel du C (connue sous le nom de cdecl
), les arguments sont poussés dans la pile dans l'ordre inverse, donc :
void myfunc(int one, int two, int three)
ressemblera à ceci sur la pile après qu'il ait été appelé (la pile grandit vers le haut, vers 0) :
. . 0x00000000
. .
. .
| current frame |
|----------------|
| return address |
|----------------| ^
| one | | stack
|----------------| | growth
| two | | direction
|----------------| |
| three |
|----------------|
| previous frame |
...
... 0xFFFFFFFF
Ainsi, le premier argument peut être récupéré en premier (car nous connaissons son emplacement, il est juste avant l'adresse de retour), et avec un peu de chance, il contient suffisamment d'informations sur le nombre d'autres arguments présents. Par exemple, dans printf(3)
et les fonctions connexes, toutes les informations sur les autres arguments sont présentes dans la chaîne de format, qui est le premier argument.
En C, les arguments des fonctions sont à la fois poussés sur la pile et retirés de celle-ci par la fonction appelante. La fonction appelante sait combien d'éléments ont été poussés et elle est donc également capable de les retirer après l'appel. Le destinataire de l'appel peut uniquement déduire le nombre d'arguments à partir d'autres paramètres, comme la chaîne de format de la fonction printf()
.
En Pascal, par exemple, les arguments sur la pile sont tirés par le destinataire de l'appel. Comme le destinataire n'est pas conscient du nombre d'éléments poussés, il ne peut pas non plus restaurer la pile à son état précédent. C'est pourquoi il est impossible d'implémenter les varargs en Pascal.