Les fonctions

Un programme conséquent peut nécessiter de reproduire le même traitement à différents moments et sur des données différentes.

Ce constat a vite amené les informaticiens à introduire un mécanisme évitant la duplication de code dans un programme. Les raisons en sont diverses :

  • Non reproduction signifie réduction de la taille du code. Historiquement, cette considération était une motivation importante lorsque la taille mémoire disponible pour le programme était limitée. Remarquons que c'est toujours le cas pour les programmes s'exécutant dans des systèmes embarqués,

  • Ne pas reproduire du code est un gain de temps pour le programmeur,

  • En cas de modification de traitement rendu nécessaire par l'évolution des objectifs ou à la suite d'une erreur, un changement unique et bien localisé et préférable à plusieurs.

Différents noms désignent ces portions de code réutilisées : routines, sous-programmes, fonctions et procédures.

Si vous avez écrit plusieurs programmes C, vous avez constaté que, bien que les objectifs de vos programmes ne soient pas identiques, des séquences d'instructions semblables se retrouvent dans chacun d'eux pour assurer des actions semblables. Ces actions sont par exemple la gestion de la liaison entre le programme et le système d'exécution, l'acquisition de données par lecture sur clavier ou dans un fichier et la restitution par écriture.

Le langage C intègre la possibilité de définir des fonctions. Celles-ci peuvent travailler avec tous les éléments visibles au regard de leurs définitions.

Le mécanisme de paramétrage est utilisé pour définir facilement les données variables sur lesquelles la fonction travaillera.

Depuis l'origine, le langage C ne fait pas de distinction syntaxique entre les fonctions qui restituent une valeur et celles sans retour exprimé, appelée par ailleurs procédure.

Une fonction est déclarée comme suit :

type nom_fonction ( type1 par1, ..., typen parn)

où :

  • type désigne un type de la valeur de retour. Dans la première version du langage, en cas d'absence de ce type, la fonction était considérée comme retournant un entier,

  • nom_fonction est l'identificateur permettant d'y faire référence,

  • type i est le type du ie paramètre,

  • pari est l'identificateur de ce ie paramètre.

La liste de paramètres peut être vide. Elle est principalement constituée d'un nombre fixe de déclarations de paramètres. Cependant, il est possible de définir des fonctions avec un nombre de paramètres variable.

Une définition de fonction a la forme suivante :

type nom_fonction ( type1 par1, ..., typen parn){

  // déclaration des variables locales

  // instructions

  // retour de la fonction

}

Le langage C offre une relative liberté dans l'organisation des constituants de la fonction. Instructions et déclarations peuvent être imbriquées et le retour de fonction est précisé avec l'instruction return :

return expression ou return(expression).

Bien que cette instruction puisse apparaître plusieurs fois dans le corps de la fonction, une programmation claire limitera ses occurrences.

En l'absence d'instruction return, le retour est aléatoire.

Si la fonction ne doit pas rendre un résultat, son type doit être void et l'expression de retour doit être vide (return;). Ce type de fonction correspond aux procédures spécifiées dans d'autres langages.

Le langage C n'offre qu'un type de passage de paramètres : le passage par valeur où la donnée transmise est une copie de la valeur du paramètre effectif défini à l'appel de la fonction (on parle aussi d'argument) au paramètre formel défini à la déclaration. La copie de la valeur est donc accessible à l'aide de l'identificateur du paramètre.

Cependant, le langage C permet un passage d'adresses grâce au pointeur. Toutefois, ceci oblige le programmeur à travailler explicitement avec le pointeur, dans :

  • La déclaration de la fonction pour préciser le type du paramètre, avec type f(type *par_pointeur);,

  • La définition pour l'accès à la donnée, avec *par_pointeur=exp;,

  • L'appel de la fonction pour la transmission du pointeur, avec var_type = f(&par_effectif);.