Sous-sections

8.2 Fonction avec un nombre variable d'arguments

Lors de l'appel à une fonction, le compilateur génère une liste des arguments fournis qu'il empile dans la pile d'exécution rattachée au processus (pile de type LIFO).

Exemple

 
int puissance(int n, int x)
{
  int p = 1;
  while(n--) p *= x;
  return p;
}
void main()
{
  int m, k, r;
  k = 4; m = 2;
  r = puissance(k+3, m);
}

A l'appel de la fonction puissance de l'exemple précédent il y a :

8.2.1 Processus de passage d'arguments

Ce type de passage d'arguments permet d'écrire des fonctions avec un nombre variable d'arguments.

Dans le prototype d'une telle fonction, on indiquera les arguments suivis de :

Comme les arguments sont rangés de façon consécutive dans la pile, le programmeur a la possibilité d'aller chercher les arguments en surnombre.

Exemple

 
void fonction(int a, ...);
main()
{
   int i = 10, j = 11, k = 12;
   printf("Avant appel fonction i = %d\n", i);
   printf("Avant appel fonction j = %d\n", j);
   printf("Avant appel fonction k = %d\n", k);
   fonction(i, j, k);
}
void fonction(int a, ...)
{
   printf("Valeur de a = %d\n", a);
   printf("Recuperation de j = %d\n", *(&a + 1));
   printf("Recuperation de k = %d\n", *(&a + 2));
}
Cette technique de récupération d'arguments dans la pile, nécessite cependant que le programmeur connaisse les types des arguments en surnombre et qu'il ait un moyen d'arrêter la recherche.

Pour ce faire, le dernier argument fourni à l'appel de la fonction peut par exemple indiquer le nombre d'arguments en surnombre, ou bien ceux-ci peuvent être suivis par un argument supplémentaire de même type avec une valeur spéciale (valeur sentinelle).

Par contre la norme ne précise pas l'ordre dans lequel les arguments doivent être empilés, cette méthode de la pile n'est donc pas portable.

Pour assurer cette portabilité, chaque système propose des pseudo-constantes et pseudo-fonctions permettant au programmeur de gérer cette recherche.

Version ANSI

Les pseudo-constantes et pseudo-fonctions sont stockées dans le fichier en-tête stdarg.h :

Les arguments en surnombre sont symbolisés par ... dans le prototype de la fonction.

Exemple

 
#include <stdio.h>
#include <stdarg.h>
main()
{
   float moyenne(int nombre, ...);
   printf("moyenne = %f\n", moyenne(4, 1, 2, 3, 4));
   printf("moyenne = %f\n",
           moyenne(5, 1, 2, 3, 4, 5));
}
float moyenne(int nombre, ...)
{
   int somme = 0, i;
   va_list arg;
   va_start(arg, nombre);
   for(i=0; i < nombre; i++)
     somme += va_arg(arg, int);
   va_end(arg);
   return somme/nombre;
}


Pr. Marc BUFFAT
buffat@ufrmeca.univ-lyon1.fr
2004-12-01