Les fonctions en langage C
Une fonction est un ensemble d'instructions qui réalise une tâche précise. Elle peut recevoir des entrées (appelées paramètres), effectuer des calculs et produire une valeur de sortie. L'idée principale consiste à regrouper des instructions utilisées fréquemment dans un même bloc afin d'éviter de répéter plusieurs fois le même code.
| Avantage | Description |
|---|---|
| Réduction de la redondance | Une opération répétée est codée une seule fois et appelée autant que nécessaire |
| Maintenance simplifiée | Une modification ne s'effectue qu'à un seul endroit dans le code |
| Organisation modulaire | Un programme complexe est découpé en modules simples et indépendants |
| Réutilisabilité | Une fonction bien écrite peut être réutilisée dans d'autres projets |
main() est le point d'entrée obligatoire de tout programme C.1. Déclaration et définition
En C, une fonction possède deux étapes distinctes : la déclaration (prototype) qui informe le compilateur de la signature, et la définition qui fournit le corps de la fonction.
/* Déclaration (prototype) — avant main() */
type_retour nom_fonction(type1 param1, type2 param2);
/* Définition — corps complet */
type_retour nom_fonction(type1 param1, type2 param2)
{
/* instructions */
return valeur; // si type_retour != void
}| Élément | Rôle | Exemple |
|---|---|---|
| Type de retour | Type de la valeur retournée (void si aucune) | int, float, void |
| Nom | Identifiant appelé dans le code | somme, Max, afficher |
| Paramètres formels | Variables locales reçues lors de l'appel | int a, int b |
| Corps | Instructions exécutées lors de l'appel | Entre { et } |
return | Retourne une valeur et quitte la fonction | return a + b; |
Exemple n°1 — Fonction somme à deux entiers
#include <stdio.h>
/* Déclaration */
int somme(int a, int b);
int main()
{
int a = 5, b = 3;
int s = somme(a, b);
printf("La somme est : %d\n", s);
return 0;
}
/* Définition */
int somme(int a, int b)
{
int c = a + b;
return c;
}La somme est : 8
Exemple n°2 — Prototypes courants
float somme(float, float); // retourne un flottant
int max(int, int); // retourne le maximum
int *echange(int *, int); // retourne un pointeur
void afficher(void); // ne retourne rien, pas de paramètresExemple n°3 — Déclaration avant main(), définition après
#include <stdio.h>
int Min(int, int); /* prototype — déclaration */
int main(void)
{
int a = 2, b = 3;
int i = Min(a, b);
printf("Minimum = %d\n", i);
return 0;
}
int Min(int i, int j) /* définition */
{
if (i < j)
return i;
else
return j;
}Minimum = 2
main() et la définir après est la pratique recommandée. Dans les projets réels, les prototypes sont placés dans un fichier d'en-tête (.h) et les définitions dans un fichier source (.c) :// math_utils.h — prototypes
int somme(int, int);
int Min(int, int);
// math_utils.c — définitions
#include "math_utils.h"
int somme(int a, int b) { return a + b; }
int Min(int i, int j) { return (i < j) ? i : j; }2. Passage des paramètres
Lors d'un appel de fonction, les valeurs envoyées sont appelées paramètres réels (ou arguments) et les variables utilisées dans la fonction sont appelées paramètres formels. Il existe deux mécanismes principaux.
| Mécanisme | Ce qui est transmis | Variable originale modifiée ? | Syntaxe côté appel |
|---|---|---|---|
| Par valeur | Une copie de la valeur | ❌ Non | f(x) |
| Par référence (pointeur) | L'adresse de la variable | ✅ Oui | f(&x) |
a. Passage par valeur
Une copie de la variable est transmise à la fonction. Les modifications effectuées dans la fonction n'affectent pas la variable originale.
Exemple n°4 — Passage par valeur
#include <stdio.h>
void incremente(int i)
{
i++; // modifie la COPIE locale, pas j
printf("i dans la fonction = %d\n", i); // 13
}
int main()
{
int j = 12;
incremente(j);
printf("j dans main = %d\n", j); // j reste 12
return 0;
}i dans la fonction = 13 j dans main = 12
j n'est pas modifiée car seule sa copie est passée à la fonction. Le paramètre formel i est une variable locale indépendante qui disparaît à la fin de la fonction.b. Passage par référence (via pointeur)
En C, tous les paramètres sont techniquement passés par valeur. Pour simuler un passage par référence — et permettre à une fonction de modifier la variable originale — on passe l'adresse de la variable à l'aide de l'opérateur &, et on accède à sa valeur via l'opérateur de déréférencement *.
/* Déclaration — paramètre pointeur */
void maFonction(int *p);
/* Appel — on passe l'adresse */
maFonction(&variable);
/* Dans la fonction — on déréférence */
(*p)++; // modifie la variable originale
*p = 42; // idemExemple n°5 — Passage par référence
#include <stdio.h>
void incremente(int *i)
{
(*i)++; // modifie la valeur à l'adresse reçue
}
int main()
{
int j = 12;
incremente(&j); // on passe l'adresse de j
printf("j = %d\n", j); // j a été modifié
return 0;
}j = 13
& et *&j— retourne l'adresse mémoire de jint *i— déclare un pointeur vers un entier*i— déréférence le pointeur : accède à la valeur stockée à cette adresse(*i)++— incrémente la valeur pointée (les parenthèses sont nécessaires car*et++ont la même priorité)
Exemple n°6 — Échange de deux variables via pointeurs
#include <stdio.h>
void echanger(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x = 10, y = 20;
printf("Avant : x = %d, y = %d\n", x, y);
echanger(&x, &y);
printf("Après : x = %d, y = %d\n", x, y);
return 0;
}Avant : x = 10, y = 20 Après : x = 20, y = 10
(*p)++ Sans parenthèses, *p++ incrémente le pointeur(il pointe vers la case mémoire suivante) et non la valeur pointée — résultat indéfini et source de bugs difficiles à détecter :(*p)++ // ✅ incrémente la VALEUR à l'adresse pointée
*p++ // ❌ incrémente le POINTEUR (comportement non voulu)3. Points importants à retenir
| Règle | Détail | Exemple |
|---|---|---|
| Fonction principale | Tout programme C possède une fonction main() | int main(void) { ... } |
Type void | Aucune valeur retournée / aucun paramètre | void afficher(void); |
| Pas de tableau en retour | Une fonction ne peut pas retourner un tableau directement | Retourner un int * (pointeur) |
| Déclarer avant usage | Sans déclaration, le compilateur suppose int f() | Toujours écrire le prototype |
| Fichiers séparés | Prototypes dans .h, définitions dans .c | #include "utils.h" |
.h) et définies dans des fichiers source (.c). Cette séparation facilite la compilation modulaire et la réutilisation :// utils.h
#ifndef UTILS_H
#define UTILS_H
int somme(int, int);
int Min(int, int);
void echanger(int *, int *);
#endif
// utils.c
#include "utils.h"
int somme(int a, int b) { return a + b; }
// main.c
#include <stdio.h>
#include "utils.h"
int main() { ... }
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.