• Aucun résultat trouvé

Fonctions prenant un nombre variable de paramètres

I. Le langage C++

1. Première approche du C/C++

1.6. Les fonctions

1.6.7. Fonctions prenant un nombre variable de paramètres

En général, les fonctions ont un nombre constant de paramètres. Pour les fonctions qui ont des pa- ramètres par défaut en C++, le nombre de paramètres peut apparaître variable à l'appel de la fonc- tion, mais en réalité, la fonction utilise toujours le même nombre de paramètres.

Cependant, le C et le C++ disposent d'un mécanisme qui permet au programmeur de réaliser des fonctions dont le nombre et le type des paramètres sont variables. Nous verrons plus loin que les fonctions d'entrée / sortie du C sont des fonctions dont la liste des arguments n'est pas fixée, cela afin de pouvoir réaliser un nombre arbitraire d'entrées / sorties, et ce sur n'importe quel type prédé- fini.

En général, les fonctions dont la liste des paramètres est arbitrairement longue disposent d'un cri- tère pour savoir quel est le dernier paramètre. Ce critère peut être le nombre de paramètres, qui peut être fourni en premier paramètre à la fonction, ou une valeur de paramètre particulière qui détermine la fin de la liste par exemple. On peut aussi définir les paramètres qui suivent le premier paramètre à l'aide d'une chaîne de caractères.

Pour indiquer au compilateur qu'une fonction peut accepter une liste de paramètres variable, il faut simplement utiliser des points de suspensions dans la liste des paramètres :

type identificateur(paramètres, ...)

dans les déclarations et la définition de la fonction. Dans tous les cas, il est nécessaire que la fonc- tion ait au moins un paramètre classique. Ces paramètres doivent impérativement être avant les points de suspensions.

La difficulté apparaît en fait dans la manière de récupérer les paramètres de la liste de paramètres dans la définition de la fonction. Les mécanismes de passage des paramètres étant très dépendants de la machine (et du compilateur), un jeu de macros a été défini dans le fichier d'en-tête stdarg.h

pour faciliter l'accès aux paramètres de la liste. Pour en savoir plus sur les macros et les fichiers d'en-tête, consulter le Chapitre 5. Pour l'instant, sachez seulement qu'il faut ajouter la ligne sui- vante :

#include <stdarg.h>

au début de votre programme. Cela permet d'utiliser le type va_list et les expressions va_start,

va_arg et va_end pour récupérer les arguments de la liste de paramètres variable, un à un. Le principe est simple. Dans la fonction, vous devez déclarer une variable de type va_list. Puis, vous devez initialiser cette variable avec la syntaxe suivante :

va_start(variable, paramètre);

où variable est le nom de la variable de type va_list que vous venez de créer, et paramètre est le dernier paramètre classique de la fonction. Dès que variable est initialisée, vous pouvez récu- pérer un à un les paramètres à l'aide de l'expressions suivantes :

Chapitre 1. Première approche du C/C++

va_arg(variable, type)

qui renvoie le paramètre en cours avec le type type et met à jour variable pour passer au para- mètre suivant. Vous pouvez utiliser cette expression autant de fois que vous le désirez, elle retourne à chaque fois un nouveau paramètre. Lorsque le nombre de paramètres correct a été récupéré, vous devez détruire la variable variable à l'aide de la syntaxe suivante :

va_end(variable);

Il est possible de recommencer les étapes suivantes autant de fois que l'on veut, la seule chose qui compte est de bien faire l'initialisation avec va_start et de bien terminer la procédure avec

va_end à chaque fois.

Note : Il existe une restriction sur les types des paramètres des listes variables d'arguments.

Lors de l'appel des fonctions, un certain nombre de traitements sur les paramètres a lieu. En particulier, des promotions implicites ont lieu, ce qui se traduit par le fait que les paramètres réellement passés aux fonctions ne sont pas du type déclaré. Le compilateur continue de faire les vérifications de type, mais en interne, un type plus grand peut être utilisé pour passer les valeurs des paramètres. En particulier, les types char et short ne sont pas utilisés : les paramètres sont toujours promus aux type int ou long int. Cela implique que les seuls types que vous pouvez utiliser sont les types cibles des promotions et les types qui ne sont pas sujets aux promotions (pointeurs, structures et unions). Les types cibles dans les promotions sont déterminés comme suit :

• les types char, signed char, unsigned char, short int ou unsigned short int sont promus en int si ce type est capable d'accepter toutes leurs valeurs. Si int est insuffisant, unsigned int est utilisé ;

• les types des énumérations (voir plus loin pour la définition des énumérations) et wchar_t sont promus en int, unsigned int, long ou unsigned long selon leurs capacités. Le premier type capable de conserver la plage de valeur du type à promouvoir est utilisé ;

• les valeurs des champs de bits sont converties en int ou unsigned int selon la taille du champ de bit (voir plus loin pour la définition des champs de bits) ;

• les valeurs de type float sont converties en double.

Exemple 1-20. Fonction à nombre de paramètres variable

#include <stdarg.h>

/* Fonction effectuant la somme de "compte" paramètres : */ double somme(int compte, ...)

{

double resultat=0; /* Variable stockant la somme. */ va_list varg; /* Variable identifiant le prochain paramètre. */

va_start(varg, compte); /* Initialisation de la liste. */ do /* Parcours de la liste. */ { resultat=resultat+va_arg(varg, double); compte=compte-1; } while (compte!=0); va_end(varg); /* Terminaison. */ return resultat; }

La fonction somme effectue la somme de compte flottants (float ou double) et la renvoie dans un double. Pour plus de détails sur la structure de contrôle do ... while, voir Section 2.4.