Variables locales et globales en langage C

31 Aug 2019 31 Aug 2019 15788 vues ESSADDOUKI Mostafa 7 min de lecture

Portée des variables

Portée (scope) La portée d'une variable est la région du programme dans laquelle cette variable est visible et utilisable. En dehors de sa portée, la variable n'existe pas — toute tentative d'y accéder provoque une erreur de compilation. En C, une variable peut être déclarée à trois endroits distincts.
Type de variableDéclarée…Visible dans…Durée de vieValeur initiale
LocaleÀ l'intérieur d'une fonction / d'un blocCe bloc uniquementDurée d'exécution du blocIndéfinie (garbage)
GlobaleEn dehors de toute fonctionToutes les fonctions du fichierDurée du programme0 / '\0' / NULL
Paramètre formelDans la signature de la fonctionCorps de la fonctionDurée d'exécution de la fonctionValeur passée par l'appelant

1. Variables locales

Variable locale Une variable déclarée à l'intérieur d'une fonction ou d'un bloc (entre {}) est dite locale. Elle n'est connue que du code situé dans ce bloc et est détruite dès que l'exécution quitte le bloc.

Exemple n°1 — Variable locale inaccessible depuis une autre fonction

void fonction_1(void)
{
    int a = 10, b = 20;   /* a et b : locales à fonction_1 */
    printf("a = %d, b = %d\n", a, b);
}

void fonction_2(void)
{
    /* printf("%d\n", a); */  /* ERREUR — a n'existe pas ici */
    printf("fonction_2 ne connaît pas a ni b\n");
}
Même nom dans des fonctions différentes Deux fonctions peuvent déclarer une variable avec le même nom sans conflit — chaque variable est indépendanteet occupe un espace mémoire distinct sur la pile :
void f1(void) { int x = 1; printf("%d\n", x); }  /* x propre à f1 */
void f2(void) { int x = 2; printf("%d\n", x); }  /* x propre à f2 — aucun conflit */

Exemple n°2 — Variable locale à un bloc if

#include <stdio.h>

int main(void)
{
    int n = 7;

    if (n > 0) {
        int double_n = n * 2;      /* locale au bloc if */
        printf("double_n = %d\n", double_n);
    }

    /* printf("%d\n", double_n); */  /* ERREUR — hors du bloc if */
    return 0;
}
Sortie
double_n = 14
Danger — Variable locale non initialisée En C, les variables locales ne sont pas initialisées automatiquement. Elles contiennent une valeur résiduelle de la mémoire (garbage value) — utiliser une telle variable produit un comportement indéfini :
int somme;                       /* valeur indéfinie */
somme += 5;                      /* résultat imprévisible */

int somme = 0;                   /* correct — toujours initialiser */
somme += 5;                      /* résultat : 5 */

2. Variables globales

Variable globale Une variable déclarée en dehors de toute fonction (généralement en haut du fichier) est dite globale. Elle est accessible depuis toutes les fonctions du programme et conserve sa valeur pendant toute la durée d'exécution.

Exemple n°3 — Variable globale partagée entre deux fonctions

#include <stdio.h>

int a;   /* variable globale — initialisée à 0 par défaut */

void fonction_1(void)
{
    a = 5;
    printf("Fonction 1 — a = %d\n", a);
}

void fonction_2(void)
{
    printf("Fonction 2 — a = %d\n", a);
}

int main(void)
{
    fonction_1();
    fonction_2();
    printf("bye\n");
    return 0;
}
Sortie
Fonction 1 — a = 5
Fonction 2 — a = 5
bye

La modification de a dans fonction_1 est visible par fonction_2 car elles partagent la même variable globale.

Masquage de la variable globale

Si une variable locale porte le même nom qu'une variable globale, la variable locale prend la priorité (masquage) à l'intérieur de sa portée. La variable globale reste inchangée.

Exemple n°4 — Variable locale masquant la variable globale

#include <stdio.h>

int a = 0;   /* variable globale */

void fonction_1(void)
{
    int a = 3;   /* variable locale — masque le a global */
    printf("Fonction 1 — a local  = %d\n", a);   /* 3 */
}

void fonction_2(void)
{
    printf("Fonction 2 — a global = %d\n", a);   /* 0 */
}

int main(void)
{
    fonction_1();
    fonction_2();
    printf("bye\n");
    return 0;
}
Sortie
Fonction 1 — a local  = 3
Fonction 2 — a global = 0
bye
Attention — Masquage silencieux Le masquage ne génère aucun avertissement par défaut. Compiler avec -Wshadow(GCC/Clang) détecte ces situations :
gcc -Wall -Wshadow programme.c -o programme
Astuce — Limiter les variables globales Les variables globales facilitent le partage de données mais rendent le code difficile à tester et à déboguer. Préférer le passage par paramètre ou le retour par valeur pour les échanges entre fonctions. Réserver les globales aux constantes ou aux données vraiment partagées par tout le programme.

3. Paramètres formels

Paramètre formel Les paramètres formels sont les variables déclarées dans la signature d'une fonction. Ils se comportent comme des variables locales : ils ne sont visibles qu'à l'intérieur de la fonction et ils masquent toute variable globale de même nom.

Exemple n°5 — Paramètre formel masquant la variable globale

#include <stdio.h>

int a = 0;   /* variable globale */

void fonction_1(int a)   /* paramètre formel nommé 'a' — masque le global */
{
    a = 3;
    printf("Fonction 1 — a (paramètre) = %d\n", a);   /* 3 */
}

void fonction_2(void)
{
    printf("Fonction 2 — a (global)    = %d\n", a);   /* 0 — inchangé */
}

int main(void)
{
    fonction_1(a);   /* passe la valeur 0, mais le paramètre est local */
    fonction_2();
    printf("bye\n");
    return 0;
}
Sortie
Fonction 1 — a (paramètre) = 3
Fonction 2 — a (global)    = 0
bye

Le paramètre a de fonction_1 est une copie locale de la valeur passée. La modifier n'affecte pas la variable globale a — c'est le passage par valeur.

4. Initialisation des variables locales et globales

TypeInitialisée automatiquement ?Valeur par défaut
Globale / StatiqueOui (par le système)Voir tableau ci-dessous
LocaleNonValeur résiduelle (garbage)
Paramètre formelOui (par l'appelant)Valeur passée en argument

Valeurs par défaut des variables globales (initialisation automatique) :

Type de donnéesValeur initiale automatique
int0
char'\0'
float0.0f
double0.0
PointeurNULL

Exemple n°6 — Contraste initialisation globale vs locale

#include <stdio.h>

int compteur_global;   /* initialisée à 0 automatiquement */

void afficher(void)
{
    int compteur_local;   /* NON initialisée — valeur imprévisible */
    printf("global = %d\n", compteur_global);
    printf("local  = %d\n", compteur_local);   /* résultat indéfini */
}

int main(void)
{
    afficher();
    return 0;
}
Bonne pratique — Toujours initialiser les variables locales Ne jamais supposer qu'une variable locale vaut 0à sa création. L'initialiser explicitement évite des bugs difficiles à reproduire :
int somme;        /* dangereux — valeur inconnue */
int somme = 0;    /* correct  — toujours initialiser */

Récapitulatif

CritèreLocaleGlobaleParamètre formel
Lieu de déclarationDans un bloc / une fonctionHors de toute fonctionSignature de fonction
PortéeBloc courant uniquementTout le fichier sourceCorps de la fonction
Durée de vieExécution du blocToute la durée du programmeExécution de la fonction
Init. automatiqueNon (garbage)Oui (0 / '\0' / NULL)Valeur de l'appelant
Masquage globalOui si même nomOui si même nom

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.