Comment fonctionne l'invocation d'une fonction de bibliothèque ?
Nous supposons que la constante PI et que l'inclusion des bibliothèques <stdio.h> et <math.h> ont été effectuées correctement. De même x est une variable qui correspond à un float.
Considérons maintenant la portion de code suivante :
instruction_avant;
x = sin(PI/4);
printf(“\nLa valeur du sinus est %f ”,x);
instruction_après;
Nous avons quatre instructions qui sont exécutées l'une à la suite de l'autre.
Nous ne détaillons pas « instruction_avant » et « instruction_après », qui sont juste là pour les besoins de l'explication.
« instruction_avant » est effectuée.
Pour la seconde instruction « x = sin(PI/4); », à droite de l'opérateur d'affectation, nous avons l'appel de la fonction sinus qui a pour paramètre le résultat de l'expression PI/4. On dit que la fonction "sin" est invoquée (ou appelée, ou utilisée) dans cette instruction. Le paramètre réel (au sens effectivement transmis) de la fonction est une valeur flottante. C'est la valeur qui est transmise par copie à la fonction pour qu'elle puisse s'exécuter. L'expression est donc calculée puis son résultat est transmis par copie à la fonction. Quand la fonction a terminé son travail elle retourne une valeur qui est un flottant. Cette valeur est ensuite affectée à la variable « x ».
Pour la troisième instruction, nous avons juste l'appel de la fonction « printf » avec deux paramètres réels. Le premier paramètre est la chaîne de caractères constante “\nLa valeur du sinus est %f” et le second paramètre est l'identificateur de la variable « x ».
La fonction reçoit donc deux valeurs. La chaîne de caractères constante et la valeur de « x ». Les deux valeurs sont transmises par copie à la fonction. La fonction « printf » utilise ces deux valeurs. Elle identifie les séquences d'échappements au sein de la chaîne de caractères et effectue les traitements appropriés.
Elle effectue l'affichage à l'écran de :
La valeur du sinus est 0.707106781187
Cette fonction « printf » ne renvoie pas de valeur.
Les fonctions en « C » retournent toujours une valeur. Ce qui semble contradictoire avec la description ci-dessus. Une fonction qui ne retourne aucune valeur retourne donc la valeur « rien », c'est-à-dire une donnée de type « void », même si aucune valeur n'est retournée.
Les fonctions en C sont typées car elles retournent toujours une valeur (void dans le cas où aucune valeur n'est à retourner).
Les fonctions permettent :
-
de décomposer une longue séquence de traitements en un ensemble de petits traitements
-
de fournir des éléments de base de haut niveau réutilisable à volonté
-
d'améliorer la lisibilité du code
-
de faciliter la maintenance d'un code
-
d'éviter la répétition de morceaux de codes identiques.
Revisitons plus en détail la séquence d'instructions :
instruction_avant;
x = sin(PI/4);
printf(“\nla valeur du sinus est %f ”,x);
instruction_après;
-
La première instruction instruction_avant est exécutée.
-
La seconde x = sin(PI/4) est exécutée. Il y a recopie d'informations, puis branchement vers la portion de code qui effectue le calcul numérique du sinus. La fonction « sin » travaille sur la donnée transmise (exécution d'instructions). Puis nous avons à nouveau un branchement pour revenir à la suite du déroulement du code. Il y a récupération de la valeur retournée par la fonction. Enfin il y a affectation de la valeur retournée (0.707) à la variable « x ».
-
A ce stade, nous sommes revenus dans le déroulement du code et prêts à exécuter l'instruction printf(“\nla valeur du sinus est %f ”,x). Il y a recopie d'informations, puis branchement vers la portion de code de « printf », la fonction « printf » travaille sur les données transmises (exécution d'instructions), puis de nouveau branchement pour revenir à la suite du déroulement du code.
-
A ce stade, nous sommes prêts à exécuter « instruction_après ».
-
Enfin, cette instruction est exécutée.
Vous avez utilisé de façon totalement transparente pour vous des recopies d'informations et des branchements. C'est le compilateur qui fait le travail pour vous.
Pour créer vos propres fonctions, il faut utiliser une syntaxe qui permet au compilateur de mettre en place ces mécanismes de recopie d'informations et de branchements. La déclaration d'une fonction a pour objet de fournir au compilateur toutes les informations nécessaires pour générer et gérer les recopies/transmissions d'informations, l'exécution des instructions de la fonction et les branchements.
Ensuite, le compilateur mettra en place les mécanismes décrits pour que votre fonction soit utilisable, à chaque fois que vous utiliserez votre fonction. Nous distinguons clairement :
-
la déclaration d'une fonction (on dit aussi définition)
-
l'usage (invocation, appel) d'une fonction connue (qui donc a été préalablement déclarée)