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 l'ancienne 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 :
Le résultat renvoyé par une fonction est l'argument d'une instruction return. Par exemple
return montant_euros * euro_en_francs;
dans conversion_euros_vers_francs de conversion.c.

Une fonction qui ne renvoie pas de résultat doit être déclarée de type void. Par exemple, la fonction message_usage dans main.c.

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 :
  1. 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.
  2. 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.
  3. 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ée à 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 de compilation #include) partout où elle est utilisée, ainsi que dans le fichier où elle est définie, de façon à assurer la cohérence entre la déclaration et la définition.
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.