Type et paramètres
L'entête d'une fonction est composée de son type, de son
identificateur, et de la liste de ses paramètres entre
parenthèses. Par exemple :
int partie_entiere(double reel)
Il existe une autre forme d'entête, datant de la première
version
du langage, qui ne sera pas utilisée dans ce cours :
int partie_entiere(reel)
double reel;
Cette entête peut être précédé d'un
mot clé : extern
ou static :
- dans le
premier cas ou si aucun mot clé n'est présent, la
fonction sera accessible depuis tous les fichiers du programme.
- La
portée d'une fonction static
se limite aux fonctions présentes dans le même fichier.
Le résultat renvoyé par une fonction est l'argument d'une
instruction return. Par
exemple
return p2;
dans puissance_de_2
de puissance_de_2.c.
Une fonction qui ne renvoie pas de résultat doit être
déclarée de type void.
Par exemple, la fonction usage
dans puissance_de_2.c.
De même, une fonction sans paramètre doit spécifier
que la liste de ses paramètres est vide à l'aide du
mot-clé void,
sinon le compilateur laissera passer les appels contenant des
paramètres. Par exemple :
int afficher_bonjour(void)
{
printf("Bonjour !");
}
Ne pas utiliser le fait qu'une
fonction qui n'est pas quittée par une instruction return renvoie le résultat de la
dernière instruction évaluée et qu'une fonction
non typée explicitement est de type int. Ce type d'erreur est signalé par
un avertissement.
Les paramètres
sont passés par valeur. Par conséquent, une fonction ne
peut changer leur valeur à l'extérieur d'elle-même.
Pour pouvoir modifier une variable, il faut passer en
paramètre son adresse. Cela s'appelle faire un passage par
référence. Le programme fonction.c
illustre ce fait :
$ fonction
entier: 1
apres appel de f: 1
apres appel de g: 2
Déclaration et définition d'une fonction
Voici la déclaration
d'une fonction carre, prenant en
paramètre un entier et retournant le carré de cet entier :
int carre(int i);
et voici sa définition
:
int
carre(int i)
{
return i * i;
}
Lorsqu'une fonction est utilisée, par exemple :
k2 = carre(k);
trois cas se présentent :
- elle
est définie après son utilisation, ou dans un autre
fichier, mais déclarée avant.
Dans ce cas, le compilateur vérifie que l'usage de la fonction
est bien compatible avec sa déclaration : nombre et types des
paramètres, type de la valeur de retour.
- elle est définie dans le
même fichier, avant son
utilisation.
Dans ce cas, la définition fait également office de
déclaration. Si une
déclaration est aussi
présente, le compilateur teste la compatibilité entre
la
déclaration et de la définition.
- elle est définie
après son utilisation, ou dans un
autre fichier, et non déclarée.
Dans ce cas, le compilateur ne teste pas le type et le nombre de
paramètres, et considère que cette fonction renvoie un int. Ce cas fait
l'objet d'un avertissement (warning) lors d'une
compilation avec l'option -Wall.
Ce cas doit absolument
être évité.
Usage
Les fonctions utilisées à l'extérieur du fichier
où elles sont définies doivent être
déclarées dans un fichier d'entête (.h). Ce fichier sera inclus
(directive du pré-processeur #include)
partout où elles sont utilisées, ainsi que dans le
fichier
où elles sont définies, de façon à garantir
la
cohérence entre les déclarations et les
définitions.
Les fonctions utilisables uniquement à l'intérieur du
fichier où elles sont définies (static) doivent
néanmoins être déclarées au début du
fichier, ce qui permet de déplacer leur définition sans
contrainte et sans risque.