PortailAccueilFAQRechercherCalendrierS'enregistrerMembresGroupesConnexion

Partagez | 
 

 Chapitre1.Première approche du C/C++ (4)

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
didouqen
Admin


Masculin
Nombre de messages : 40
Age : 31
Localisation : Marrakech
Date d'inscription : 07/09/2006

MessageSujet: Chapitre1.Première approche du C/C++ (4)   Mar 25 Sep - 6:50

1.6.5. Fonctions inline
Le C++ dispose du mot clé inline, qui permet de modifier la méthode d'implémentation des fonctions. Placé devant la déclaration d'une fonction, il propose au compilateur de ne pas instancier cette fonction. Cela signifie que l'on désire que le compilateur remplace l'appel de la fonction par le code correspondant. Si la fonction est grosse ou si elle est appelée souvent, le programme devient plus gros, puisque la fonction est réécrite à chaque fois qu'elle est appelée. En revanche, il devient nettement plus rapide, puisque les mécanismes d'appel de fonctions, de passage des paramètres et de la valeur de retour sont ainsi évités. De plus, le compilateur peut effectuer des optimisations additionnelles qu'il n'aurait pas pu faire si la fonction n'était pas inlinée. En pratique, on réservera cette technique pour les petites fonctions appelées dans du code devant être rapide (à l'intérieur des boucles par exemple), ou pour les fonctions permettant de lire des valeurs dans des variables.
Cependant, il faut se méfier. Le mot clé inline est un indice indiquant au compilateur de faire des fonctions inline. Il n'y est pas obligé. La fonction peut donc très bien être implémentée classiquement. Pire, elle peut être implémentée des deux manières, selon les mécanismes d'optimisation du compilateur. De même, le compilateur peut également inliner les fonctions normales afin d'optimiser les performances du programme.
De plus, il faut connaître les restrictions des fonctions inline :
• elles ne peuvent pas être récursives ;
• elles ne sont pas instanciées, donc on ne peut pas faire de pointeur sur une fonction inline.
Si l'une de ces deux conditions n'est pas vérifiée pour une fonction, le compilateur l'implémentera classiquement (elle ne sera donc pas inline).
Enfin, du fait que les fonctions inline sont insérées telles quelles aux endroits où elles sont appelées, il est nécessaire qu'elles soient complètement définies avant leur appel. Cela signifie que, contrairement aux fonctions classiques, il n'est pas possible de se contenter de les déclarer pour les appeler, et de fournir leur définition dans un fichier séparé. Dans ce cas en effet, le compilateur générerait des références externes sur ces fonctions, et n'insérerait pas leur code. Ces références ne seraient pas résolues à l'édition de lien, car il ne génère également pas les fonctions inline, puisqu'elles sont supposées être insérées sur place lorsqu'on les utilise. Les notions de compilation dans des fichiers séparés et d'édition de liens seront présentées en détail dans le Chapitre 6.
Exemple 1-18. Fonction inline
inline int Max(int i, int j)
{
if (i>j)
return i;
else
return j;
}
Pour ce type de fonction, il est tout à fait justifié d'utiliser le mot clé inline.
1.6.6. Fonctions statiques
Par défaut, lorsqu'une fonction est définie dans un fichier C/C++, elle peut être utilisée dans tout autre fichier pourvu qu'elle soit déclarée avant son utilisation. Dans ce cas, la fonction est dite externe. Il peut cependant être intéressant de définir des fonctions locales à un fichier, soit afin de résoudre des conflits de noms (entre deux fonctions de même nom et de même signature mais dans deux fichiers différents), soit parce que la fonction est uniquement d'intérêt local. Le C et le C++ fournissent donc le mot clé static qui, une fois placé devant la définition et les éventuelles déclarations d'une fonction, la rend unique et utilisable uniquement dans ce fichier. ہ part ce détail, les fonctions statiques s'utilisent exactement comme des fonctions classiques.
Exemple 1-19. Fonction statique
// Déclaration de fonction statique :
static int locale1(void);

/* Définition de fonction statique : */
static int locale2(int i, float j)
{
return i*i+j;
}
Les techniques permettant de découper un programme en plusieurs fichiers sources et de générer les fichiers binaires à partir de ces fichiers seront décrites dans le chapitre traitant de la modularité des programmes.
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 paramètres par défaut en C++, le nombre de paramètres peut apparaître variable à l'appel de la fonction, mais en réalité, la fonction utilise toujours le même nombre de paramètres.
Le C et le C++ disposent toutefois 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 critè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 fonction ait au moins un paramètre classique. Les paramètres classiques 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 suivante :
#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écupérer un à un les paramètres à l'aide de l'expression suivante :
va_arg(variable, type)
qui renvoie le paramètre en cours avec le type type et met à jour variable pour passer au paramè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 ces étapes 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 a lieu sur les paramètres. 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. */
while (compte!=0) /* Parcours de la liste. */
{
resultat=resultat+va_arg(varg, double);
compte=compte-1;
}
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 while, voir Section 2.3.
1.7. La fonction main
Lorsqu'un programme est chargé, son exécution commence par l'appel d'une fonction spéciale du programme. Cette fonction doit impérativement s'appeler « main » (principal en anglais) pour que le compilateur puisse savoir que c'est cette fonction qui marque le début du programme. La fonction main est appelée par le système d'exploitation, elle ne peut pas être appelée par le programme, c'est-à-dire qu'elle ne peut pas être récursive.
Exemple 1-21. Programme minimal
int main() /* Plus petit programme C/C++. */
{
return 0;
}
La fonction main doit renvoyer un code d'erreur d'exécution du programme, le type de ce code est int. Elle peut aussi recevoir des paramètres du système d'exploitation. Ceci sera expliqué plus loin. Pour l'instant, on se contentera d'une fonction main ne prenant pas de paramètre.
Note : Il est spécifié dans la norme du C++ que la fonction main ne doit pas renvoyer le type void. En pratique cependant, beaucoup de compilateurs l'acceptent également.
La valeur 0 retournée par la fonction main indique que tout s'est déroulé correctement. En réalité, la valeur du code de retour peut être interprétée différemment selon le système d'exploitation utilisé. La bibliothèque C définit donc les constantes EXIT_SUCCESS et EXIT_FAILURE, qui permettent de supprimer l'hypothèse sur la valeur à utiliser respectivement en cas de succès et en cas d'erreur.
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://didouqen.ousama.free.fr
 
Chapitre1.Première approche du C/C++ (4)
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» Première approche étrange ...
» Première construction diapo
» Photos de l'avant-première des bagnoles 2
» Avant première historique !
» Première facture oui mais ... pas sûr de l'adresse pour payer

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
DESIGN STUDIO FORUM :: programmation :: C,C++-
Sauter vers: