Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 30

Passage de Paramètres : Valeur vs Référence

Recommended resources

Bonjour ! Dans la leçon précédente, nous avons vu la distinction fondamentale entre les variables locales et globales, et l'importance de créer des fonctions autonomes qui ne dépendent pas de l'état global du programme. C'est une étape cruciale vers votre objectif d'écrire du "code clean".

Aujourd'hui, nous allons nous pencher sur le mécanisme de communication principal avec les fonctions : les paramètres. Nous allons répondre à une question essentielle : lorsque nous passons une variable à une fonction, celle-ci peut-elle modifier la variable d'origine ? La réponse dépend de la manière dont le paramètre est passé.

L'objectif de cette leçon est donc d'expliquer la différence entre le passage de paramètres par valeur et par référence. Comprendre ces deux mécanismes est indispensable pour maîtriser le comportement de vos fonctions et éviter les bugs subtils.

1. Le Passage par Valeur : La "Photocopie"

Le passage par valeur est le mécanisme le plus courant et le plus sûr.

Le principe : Quand vous passez une variable à une fonction "par valeur", le système ne transmet pas la variable elle-même, mais une copie de sa valeur. La fonction travaille alors sur cette copie, qui est une variable locale comme les autres. Toute modification apportée à cette copie à l'intérieur de la fonction n'a aucun impact sur la variable originale dans le programme qui a fait l'appel.

Analogie : C'est comme si vous me donniez une photocopie d'un document important. Je peux écrire, dessiner ou raturer ma copie autant que je veux, votre document original restera intact.

Pour formaliser cela, nous allons nous appuyer sur un document de cours.

Initiation à l'Algorithmique Cours et exercices corrigés

Le document 'Initiation à l'Algorithmique' définit clairement les deux modes de passage de paramètres et illustre parfaitement le passage par valeur.

Commencez par lire la section 2.3 'Le passage de paramètres' (page 46). Concentrez-vous sur la définition du 'passage par valeur'. Ensuite, analysez attentivement l'Exemple 3 de la section 4 (page 49), qui montre un algorithme nommé 'C' et son déroulement. Remarquez bien le commentaire : 'le x local est modifié, pas le x du programme principal'.

Analysons l'exemple Algorithme C du document.

Pseudo-code :

Algorithme C

Var x : entier // Variable globale

Procédure Modif(x : entier) // 'x' est un paramètre local (passé par valeur)
Début
  x ← x + 1 // On modifie la COPIE de x
Fin

Début // Algorithme principal
  x ← 1
  Ecrire("Valeur de x avant l’appel : ", x) // Affiche 1

  Modif(x) // On passe une copie de la valeur de x (qui est 1)

  Ecrire("Valeur de x après l’appel : ", x) // Affiche TOUJOURS 1
Fin

Déroulement :

  1. Dans le programme principal, la variable globale x est créée et initialisée à 1.
  2. L'appel Modif(x) est exécuté.
  3. Une nouvelle variable locale à la procédure Modif, qui s'appelle aussi x, est créée.
  4. La valeur de la variable globale x (c'est-à-dire 1) est copiée dans cette nouvelle variable locale.
  5. À l'intérieur de Modif, l'instruction x ← x + 1 s'applique à la variable locale. Sa valeur devient 2. La variable globale reste inchangée à 1.
  6. La procédure Modif se termine. Toutes ses variables locales, y compris son paramètre x, sont détruites.
  7. De retour dans le programme principal, Ecrire affiche la valeur de la variable globale x, qui n'a jamais été modifiée : 1.

Le passage par valeur est donc un mécanisme de protection. Il garantit qu'une fonction ne peut pas produire d'effets de bord en modifiant les variables du programme appelant.


2. Le Passage par Référence : L'"Adresse"

Parfois, nous voulons intentionnellement qu'une fonction modifie une variable. C'est là qu'intervient le passage par référence.

Le principe : Au lieu de passer une copie de la valeur, le système transmet une référence à la variable originale. On peut voir cette référence comme l'adresse mémoire de la variable. La fonction ne travaille donc plus sur une copie, mais directement sur la variable originale. Toute modification est donc répercutée à l'extérieur de la fonction.

Analogie : Cette fois, au lieu d'une photocopie, je vous donne l'adresse exacte (le numéro du tiroir et du dossier) où se trouve mon document original. Si vous allez à cette adresse et modifiez le document, c'est bien l'original qui est modifié.

L'image suivante illustre bien cette différence fondamentale.

Passage par Valeur vs. Passage par Référence
Cette image compare les deux mécanismes. À gauche (par valeur), la fonction reçoit une copie de la valeur (5). À droite (par référence), la fonction reçoit une référence (l'adresse de `x`), lui permettant de modifier l'objet original.

Pour comprendre le fonctionnement en détail, nous allons utiliser une ressource qui schématise la mémoire.

[PDF] Chapitre G II LES FONCTIONS et LES PROCEDURES - Lamsade

Le document '[PDF] Chapitre G II LES FONCTIONS et LES PROCEDURES' explique de manière très détaillée le passage par référence, qu'il nomme 'passage par variable' ou 'par adresse'. Nous allons nous concentrer sur l'exemple classique de l'échange de deux valeurs.

Lisez d'abord le point 1 dans 'A. GENERALITES SUR LES PROCEDURES' (page 2) pour comprendre le concept et la terminologie ('passage par variable, passage par référence ou passage par adresse'). Ensuite, sautez à la section 'C. Les paramètres d'entrée-sortie' (page 5) et étudiez l'exemple de la procédure 'échange' (page 5-6). Observez comment les paramètres sont déclarés comme 'entrée sortie' et comment les schémas de la RAM illustrent que la procédure modifie directement les variables globales x et y.

Reprenons cet exemple d'échange de variables, qui est un cas d'usage parfait pour le passage par référence.

Pseudo-code :

// La mention 'en entrée/sortie' indique un passage par référence
Procédure Echange(a: entier en entrée/sortie, b: entier en entrée/sortie)
  Variables
    temp: entier
  Début
    temp ← a
    a ← b
    b ← temp
  Fin

Algorithme Principal
  Variables
    var1: entier
    var2: entier
  Début
    var1 ← 5
    var2 ← 10
    Ecrire("Avant : var1=", var1, ", var2=", var2) // Affiche 5, 10

    // On passe les variables elles-mêmes (leurs adresses)
    Echange(var1, var2)

    Ecrire("Après : var1=", var1, ", var2=", var2) // Affiche 10, 5
  Fin

Déroulement :

  1. Dans le programme principal, var1 est 5 et var2 est 10.
  2. L'appel Echange(var1, var2) est exécuté.
  3. Le paramètre a de la procédure Echange devient une référence vers var1. Le paramètre b devient une référence vers var2.
  4. À l'intérieur de Echange :
    • temp ← a : temp reçoit la valeur de var1 (via la référence a), donc temp vaut 5.
    • a ← b : la variable var1 (pointée par a) reçoit la valeur de var2 (pointée par b). var1 vaut maintenant 10.
    • b ← temp : la variable var2 (pointée par b) reçoit la valeur de temp. var2 vaut maintenant 5.
  5. La procédure se termine. Les variables var1 et var2 ont été permutées.

3. Quand utiliser l'un ou l'autre ?

Le choix entre passage par valeur et par référence est une décision de conception importante qui influence la propreté de votre code.

Mécanisme Passage par Valeur Passage par Référence
Principe La fonction reçoit une copie. La fonction reçoit une référence (adresse).
Effet La variable originale est protégée. La variable originale peut être modifiée.
Quand l'utiliser ? Par défaut. Chaque fois qu'une fonction a juste besoin de lire une valeur pour faire un calcul. Avec intention, quand une fonction doit :
1. Modifier la variable appelante (ex: Echange).
2. "Retourner" plusieurs résultats.
Avantage "Code Clean" Empêche les effets de bord, rend les fonctions prévisibles et autonomes. Permet des modifications d'état explicites et contrôlées.

En règle générale, pour un code propre et facile à déboguer :

  • Privilégiez le passage par valeur autant que possible.
  • Utilisez le passage par référence uniquement lorsque c'est nécessaire et justifié par la logique de votre algorithme.

4. À vous de jouer

Pour vérifier votre compréhension, analysez le petit algorithme ci-dessous et prédisez les valeurs finales de a et b.

// Passage par valeur
Procédure AjouteDix_Valeur(param_val: entier)
  Début
    param_val ← param_val + 10
    Ecrire("-> Dans AjouteDix_Valeur, le paramètre vaut : ", param_val)
  Fin

// Passage par référence
Procédure AjouteDix_Ref(param_ref: entier en entrée/sortie)
  Début
    param_ref ← param_ref + 10
    Ecrire("-> Dans AjouteDix_Ref, le paramètre vaut : ", param_ref)
  Fin

Algorithme Principal
  Variables
    a: entier ← 100
    b: entier ← 100
  Début
    Ecrire("Initialement, a=", a, " et b=", b)

    AjouteDix_Valeur(a)
    AjouteDix_Ref(b)

    Ecrire("Finalement, a=", a, " et b=", b)
  Fin
Cliquez ici pour voir la solution et le déroulement

Résultat de l'exécution :

Initialement, a=100 et b=100
-> Dans AjouteDix_Valeur, le paramètre vaut : 110
-> Dans AjouteDix_Ref, le paramètre vaut : 110
Finalement, a=100 et b=110

Explication :

  1. AjouteDix_Valeur(a) : La procédure reçoit une copie de la valeur de a (100). Elle ajoute 10 à cette copie (qui devient 110) et l'affiche. La variable originale a n'est pas touchée.
  2. AjouteDix_Ref(b) : La procédure reçoit une référence vers b. Quand elle ajoute 10, elle modifie directement la variable originale b. La valeur de b dans le programme principal passe donc de 100 à 110.
  3. L'affichage final confirme que a est restée à 100, tandis que b a été modifiée et vaut 110.

Conclusion

Aujourd'hui, nous avons décortiqué un mécanisme fondamental de la programmation : la manière dont les informations circulent entre les différentes parties d'un algorithme.

Points clés à retenir :

  • Passage par valeur : C'est le mode "sécurisé". La fonction travaille sur une copie et ne peut pas altérer l'original. C'est le choix par défaut pour un code prévisible.
  • Passage par référence : C'est le mode "puissant" qui donne à une fonction la permission de modifier la variable originale. Il est indispensable pour certaines tâches, comme l'échange de valeurs ou quand une procédure doit retourner plusieurs résultats.
  • La maîtrise de ces deux modes vous donne un contrôle total sur le comportement de vos fonctions et les données de votre programme.

Et après ?

Maintenant que nous savons définir des fonctions, gérer la portée des variables et contrôler la manière dont elles communiquent via les paramètres, nous avons tous les outils en main pour nous attaquer à des problèmes plus ambitieux. Dans la prochaine leçon, nous apprendrons à décomposer un problème complexe en plusieurs fonctions modulaires, la pierre angulaire de la conception de programmes structurés, lisibles et faciles à maintenir.