Portée des variables : variables locales et globales#

Nous avons vu dans les cours précédents que l’on pouvait déclarer des variables à différents endroits :

  • Directement dans une cellule Jupyter ou l’entête d’un programme :

    int a = 1;
    
  • Dans une boucle for :

    for ( int a = 0; i <= 5; i ++ ) {
        ...
    }
    
  • Comme paramètre d’une fonction :

    int f(int a) {
        ...
    }
    
  • Dans le corps d’une fonction :

    int f() {
        int a;
        ...
    }
    
  • Et en fait, plus généralement, dans un bloc :

    {
        int a;
        ...
    }
    

Objectif pédagogique

Formaliser les cas précédents en introduisant la notion de portée d’une variable.

Quelques exemples#

Dans un programme, le même nom peut être utilisé pour plusieurs variables, ce qui peut amener des ambiguïtés.

Exercice

  1. Devinez le résultat des commandes suivantes.

int i = 1;
{
    i = 2;
    i = i + 1;
}
i
int i = 1;
{
    int i = 2;
    i = i + 1;
}
i
int i = 1;
for ( int i = 1; i < 10; i++ ) {
    int i;
}
i
#include <iostream>
using namespace std;
int a = 0, b = 0;
void f(int b) {
    int c = 5;
    cout << "1: " << a << " " << b << " " << c << endl;
}
void g() {
    int a = 2, c = 2;
    cout << "2: " << a << " " << b << " " << c << endl;
    {
        long a = 3, c = 3;
        cout << "3: " << a << " " << b << " " << c << endl;
    }
    cout << "4: " << a << " " << b << " " << c << endl; 
    f(4);
}
g()

La réponse pourrait en fait dépendre du langage!

Pour prédire rigoureusement le comportement du programme, il faut préciser la sémantique des variables et notamment leur portée.

La portée des variables#

En C++, comme dans la plupart des langages modernes, la portée d’une variable (où elle est définie) est déterminée par le contexte lexical (comment le code est écrit) sans avoir à considérer le contexte d’exécution (comment le code s’exécute). Cela permet en effet de raisonner localement à une fonction, à un fichier, sans se préocuper du reste du programme.

Sémantique#

Définition : Portée des variables

Une variable est visible depuis sa déclaration jusqu’à la fin du bloc { ... } où elle est déclarée.

Cas particuliers

Dans le cas d’une boucle for, on considère l’entête comme étant dans le bloc for (int i ...) { ... }.

Définition : Variables locales, paramètres formels et variables globales

  • Une variable locale (local variable) est définie dans un bloc (par exemple d’une fonction).

  • Un paramètre formel (formal parameter) est défini dans l’entête d’une fonction; il se comporte comme une variable locale du bloc de la fonction.

  • Une variable globale (global variable) est définie ailleurs (cellule Jupyter, entête de programme)

Attention

Une variable peut masquer des variables issues des contextes englobants!

Exercice

Reprenez l’exemple ci-dessus, et annotez chaque déclaration et chaque utilisation de variable : quelles variables y sont locales, globales, … Puis exécutez le pas-à-pas en dessinant la pile d’exécution pour prédire à nouveau l’affichage. Vérifiez.

Solution

int a = 0, b = 0;                  // Variables globales
void f(int b) {                    // Paramètre (donc local à f)
    int c = 5;                     // Variable locale de f
    // a: globale; b: paramètre de f; c: local à f
    cout << "1: " << a << " " << b << " " << c << endl;
}
void g() {
    int a = 2, c = 2;              // Variables locales à g
    // a, c: locales à g; b: globale
    cout << "2: " << a << " " << b << " " << c << endl;
    {
        long a = 3, c = 3;         // Variables locales au bloc
        // a, c: locales au bloc; b: globale
        cout << "3: " << a << " " << b << " " << c << endl;
    }
    // a, c: locales à g; b: globale
    cout << "4: " << a << " " << b << " " << c << endl; 
    f(4);
}
g()

Rappels#

  • Une variable locale à une fonction n’existe que le temps d’exécution de la fonction

  • La valeur de cette variable d’un appel à la fonction est perdue lors du retour au programme appelant et ne peut pas être récupérée lors d’un appel ultérieur

Variables globales : bonnes pratiques#

  • Accessible à l’intérieur de toutes les fonctions

  • On peut modifier la valeur d’une variable globale
    Ceci est déconseillé (effet de bord)

  • Une variable locale masque une variable globale du même nom
    Ceci est déconseillé (ambiguïté à la lecture rapide)

  • On évitera ces pratiques dans le cadre de ce cours

Résumé: portée des variables#

  • Une variable est définie depuis sa déclaration jusqu’à la fin du bloc la contenant
    (en considérant l’entête d’une fonction ou d’une boucle for comme faisant partie du bloc)

  • Une variable hors de tout bloc est dite globale En général, on évite les variables globales

  • Sinon elle est locale