web-dev-qa-db-fra.com

Variable statique à l'intérieur d'une fonction en C

Qu'est-ce qui sera imprimé? 6 6 ou 6 7? Et pourquoi?

void foo()
{
    static int x = 5;
    x++;
    printf("%d", x);
}

int main()
{
    foo();
    foo();
    return 0;
}
94
Vadiklk

Il y a deux problèmes ici, la durée de vie et la portée.

La portée de la variable est l'endroit où le nom de la variable peut être vu. Ici, x n'est visible que dans la fonction foo ().

La durée de vie d'une variable est la période sur laquelle elle existe. Si x était défini sans le mot-clé static, la durée de vie serait de l'entrée dans foo () au retour de foo (); il serait donc réinitialisé à 5 à chaque appel.

Le mot-clé static agit pour prolonger la durée de vie d'une variable jusqu'à la durée de vie du programme. par exemple. l'initialisation se produit une fois et une fois seulement, puis la variable conserve sa valeur - quelle qu'elle soit maintenant - pour tous les futurs appels à foo ().

143
user82238

Sortie : 6 7

Reason : la variable statique n'est initialisée qu'une fois (contrairement à la variable auto) et toute définition supplémentaire de la variable statique serait ignorée lors de l'exécution. Et si ce n’est pas initialisé manuellement, il est automatiquement initialisé avec la valeur 0 . 

void foo() {
    static int x = 5; // assigns value of 5 only once
    x++;
    printf("%d", x);
}

int main() {
    foo(); // x = 6
    foo(); // x = 7
    return 0;
}
37
Nitesh Borad

C'est la même chose que d'avoir le programme suivant:

static int x = 5;

void foo()
{
    x++;
    printf("%d", x);
}

int main()
{
     foo();
     foo();
     return 0;
}

Tout ce que le mot clé static fait dans ce programme, c'est qu'il indique au compilateur (essentiellement): "Hé, j'ai une variable ici que je ne veux pas que quelqu'un d'autre accède, ne dites à personne d'autre qu'il existe.".

Dans une méthode, le mot-clé static indique au compilateur la même chose que ci-dessus, mais également: "ne dites à personne que cela existe en dehors de cette fonction, il ne devrait être accessible qu'à l'intérieur de cette fonction".

J'espère que ça aide 

9
Richard J. Ross III

6 7

le compilateur fait en sorte que l'initialisation d'une variable statique ne se produise pas à chaque fois que la fonction est entrée

8
Chaim Geretz

Une variable statique dans une fonction a une durée de vie aussi longue que votre programme. Il ne sera pas attribué à chaque fois que votre fonction est appelée et désallouée au retour de votre fonction.

5
Donotalo

Vadiklk,

Pourquoi ...? La raison est que la variable statique n’est initialisée qu’une seule fois et conserve sa valeur tout au long du programme . Signifie que vous pouvez utiliser la variable statique entre les appels de fonction . " 

main()
{
   static int var = 5;
   printf("%d ",var--);
   if(var)
      main();
} 

et la réponse est 5 4 3 2 1 et non 5 5 5 5 5 5 .... (boucle infinie) comme vous vous attendez . Encore une fois, la raison est la variable statique est initialisée une fois, lorsque la prochaine fois que main () est appelée il ne sera pas initialisé à 5 car il est déjà initialisé dans le programme.Alors on peut changer la valeur mais ne peut pas être réinitialisé. Thats comment la variable statique fonctionne. 

ou vous pouvez considérer selon le stockage: les variables statiques sont stockées dans la section de données d'un programme et les variables stockées dans la section de données sont initialisées une fois. et avant l'initialisation, ils sont conservés dans la section BSS.

À leur tour, les variables auto (locales) sont stockées sur la pile et toutes les variables de la pile sont réinitialisées à tout moment lorsque la fonction est appelée lorsqu'un nouvel enregistrement d'activation de fonction (FAR) est créé à cet effet.

ok pour plus de compréhension, faites l'exemple ci-dessus sans "statique" et vous permettent de savoir quelle sera la sortie. Cela vous fait comprendre la différence entre ces deux.

Merci Javed

2
Javed

La sortie sera 6 7. Une variable statique (que ce soit à l'intérieur d'une fonction ou non) est initialisée exactement une fois, avant l'exécution de toute fonction de l'unité de traduction. Après cela, il conserve sa valeur jusqu'à ce qu'il soit modifié.

2
Jerry Coffin

6 et 7 Parce que la variable statique initialise une seule fois, Donc, 5 ++ devient 6 au premier appel. 6 ++ devient 7 au 2e appel Remarque: lorsque le 2e appel a lieu, la valeur x est 6 et non 5 car x est une variable statique.

1
Tushar shirsath

Sortie: 6,7

Raison

La déclaration de x est dans foo mais l'initialisation x=5 a lieu en dehors de foo!

Ce que nous devons comprendre ici est que 

static int x = 5;

n'est pas la même chose que

static int x;
x = 5;

D'autres réponses ont utilisé les mots importants ici, portée et durée de vie, et ont souligné que la portée de x allait du point de sa déclaration dans la fonction foo à la fin de la fonction foo. Par exemple, j'ai vérifié en déplaçant la déclaration à la fin de la fonction, ce qui rend x non déclaré à l'instruction x++;.

Ainsi, la partie static int x (portée) de la déclaration s’applique réellement à l’endroit où vous la lisez, quelque part DANS la fonction et uniquement à partir de là, pas au-dessus de celle-ci dans la fonction.

Cependant, la partie x = 5 (durée de vie) de l'instruction est initialisation de la variable et passe EN DEHORS DE de la fonction lors du chargement du programme. La variable x est créée avec une valeur de 5 lors du chargement du programme.

J'ai lu ceci dans l'un des commentaires: "cela ne concerne pas non plus la partie qui prête vraiment à confusion, c'est-à-dire que l'initialiseur est ignoré lors d'appels suivants." Il est ignoré pour tous les appels. L'initialisation de la variable est en dehors du code de fonction proprement dit.

La valeur de 5 est théoriquement définie indépendamment du fait que foo soit appelé ou non, bien qu'un compilateur puisse optimiser la fonction si vous ne l'appelez nulle part. La valeur de 5 doit être dans la variable avant que foo ne soit appelé.

Dans foo, il est peu probable que l'instruction static int x = 5; génère du code.

J'ai trouvé l'adresse x utilisée lorsque je mets une fonction foo dans un de mes programmes, puis j'ai deviné (correctement) que le même emplacement serait utilisé si je réexécutais le programme. La capture d'écran partielle ci-dessous montre que x a la valeur 5 même avant le premier appel à foo.

 Break Point before first call to foo

1
user3070485

Lisons simplement l'article Wikipedia sur les variables statiques ...

Variables locales statiques: les variables déclarées comme statiques dans une fonction sont allouées statiquement tout en ayant la même portée que les variables locales automatiques. Par conséquent, quelles que soient les valeurs que la fonction met dans ses variables locales statiques lors d'un appel, il sera toujours présent lorsque la fonction sera appelée à nouveau.

1
Andrew White

Vous aurez 6 7 imprimé comme, comme cela a été facilement testé, et voici la raison: lorsque foo est appelé pour la première fois, la variable statique x est initialisée à 5. Elle est ensuite incrémentée à 6 et imprimée.

Passons maintenant au prochain appel à foo. Le programme ignore l'initialisation de la variable statique et utilise à la place la valeur 6 attribuée à x la dernière fois. L'exécution se déroule normalement et vous donne la valeur 7.

1
Ken Wayne VanderLinde
6 7

x est une variable globale visible uniquement depuis foo (). 5 est sa valeur initiale, telle que stockée dans la section .data du code. Toute modification ultérieure écrase la valeur précédente. Aucun code d’affectation n’est généré dans le corps de la fonction.

1
mouviciel

En C++ 11 au moins, lorsque l'expression utilisée pour initialiser une variable statique locale n'est pas un 'constexpr' (ne peut pas être évaluée par le compilateur), l'initialisation doit avoir lieu lors du premier appel à la fonction. L'exemple le plus simple consiste à utiliser directement un paramètre pour initialiser la variable statique locale. Ainsi, le compilateur doit émettre du code pour deviner si l'appel est le premier ou non, ce qui nécessite à son tour une variable booléenne locale. J'ai compilé un tel exemple et vérifié que cela est vrai en consultant le code d'assemblage. L'exemple peut être comme ça:

void f( int p )
{
  static const int first_p = p ;
  cout << "first p == " << p << endl ;
}

void main()
{
   f(1); f(2); f(3);
}

bien sûr, lorsque l'expression est 'constexpr', cela n'est pas obligatoire et la variable peut être initialisée lors du chargement du programme en utilisant une valeur stockée par le compilateur dans le code d'assemblage en sortie.

0
user5122888