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;
}
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;
}
Réponses:
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 étendre la durée de vie d'une variable à la durée de vie du programme; par exemple, l'initialisation se produit une seule fois et une seule fois, puis la variable conserve sa valeur - quelle qu'elle soit - sur tous les futurs appels à foo ().
Sortie : 6 7
Raison : la variable statique n'est initialisée qu'une seule fois (contrairement à la variable automatique) et une définition plus poussée de la variable statique serait contournée pendant l'exécution. Et s'il n'est pas initialisé manuellement, il est automatiquement initialisé par la valeur 0. Alors,
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;
}
6 7
le compilateur fait en sorte que l'initialisation de la variable statique ne se produise pas à chaque fois que la fonction est entrée
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 fait le mot-clé static dans ce programme, c'est qu'il dit au compilateur (essentiellement) "hé, j'ai une variable ici à laquelle je ne veux pas que quelqu'un d'autre accède, ne dis à personne d'autre qu'elle existe".
Dans une méthode, le mot-clé static dit au compilateur la même chose que ci-dessus, mais aussi, «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
x
in main; c'est mondial. Dans l'exemple d'origine, il x
était local à foo, visible uniquement à l'intérieur de ce bloc, ce qui est généralement préférable: si foo existe pour être maintenu x
de manière prévisible et visible, alors laisser les autres le pousser est généralement dangereux. Comme autre avantage de le garder dans la portée, foo()
il reste également foo()
portable.
c
, donc dans ce contexte, votre exemple serait illégal à l'échelle mondiale. (C nécessite des initialiseurs constants pour les globaux, C ++ ne le fait pas).
Une variable statique à l'intérieur d'une fonction a une durée de vie tant que votre programme s'exécute. Elle ne sera pas allouée à chaque fois que votre fonction est appelée et désallouée au retour de votre fonction.
La déclaration de x
est à l'intérieur foo
mais l' x=5
initialisation a lieu à l'extérieur de foo
!
Ce que nous devons comprendre ici, c'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
va 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, et cela rend x
non déclaré à l' x++;
instruction.
Ainsi, la partie static int x
(portée) de l'instruction s'applique réellement là où vous la lisez, quelque part DANS la fonction et seulement à partir de là, pas au-dessus d'elle à l'intérieur de la fonction.
Cependant, la partie x = 5
(durée de vie) de l'instruction est l' initialisation de la variable et se produit À L'EXTÉRIEUR de la fonction dans le cadre du chargement du programme. La variable x
est née avec une valeur de 5
quand le programme se charge.
J'ai lu ceci dans l'un des commentaires: " De plus, cela ne résout pas la partie vraiment déroutante, qui est le fait que l'initialiseur est ignoré lors des appels suivants. " Il est ignoré sur 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é.
À l'intérieur de foo
, il static int x = 5;
est peu probable que l'instruction génère du code.
J'ai trouvé l'adresse x
utilisée lorsque j'ai mis une fonction foo
dans un de mes programmes, puis j'ai (correctement) deviné que le même emplacement serait utilisé si je réexécutais le programme. La capture d'écran partielle ci-dessous montre qu'elle x
a la valeur 5
même avant le premier appel à foo
.
La sortie sera 6 7
. Une variable statique (qu'elle soit à l'intérieur d'une fonction ou non) est initialisée exactement une fois, avant l'exécution d'une fonction de cette unité de traduction. Après cela, il conserve sa valeur jusqu'à ce qu'il soit modifié.
Vadiklk,
Pourquoi ...? La raison en 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 une variable statique entre les appels de fonction. il peut également être utilisé pour compter "combien de fois une fonction est appelée"
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 y attendez. encore une fois, la raison est que la variable statique est initialisée une fois, lors du prochain appel de main (), elle ne sera pas initialisée à 5 car elle est déjà initialisée dans le programme. Nous pouvons donc changer la valeur mais ne pouvons pas la réinitialiser. Voilà comment fonctionne la variable statique.
ou vous pouvez considérer comme par stockage: les variables statiques sont stockées sur la section de données d'un programme et les variables qui sont 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 automatiques (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 en tant que nouveau FAR (enregistrement d'activation de fonction) est créé pour cela.
ok pour plus de compréhension, faites l'exemple ci-dessus sans "statique" et faites-vous savoir quelle sera la sortie. Cela vous fait comprendre la différence entre les deux.
Merci Javed
Lisons simplement l'article de Wikipedia sur les variables statiques ...
Variables locales statiques: les variables déclarées comme statiques à l'intérieur d'une fonction sont allouées statiquement tout en ayant la même portée que les variables locales automatiques. Par conséquent, toutes les valeurs que la fonction met dans ses variables locales statiques lors d'un appel seront toujours présentes lorsque la fonction est appelée à nouveau.
Vous obtiendrez 6 7 imprimés comme, comme cela est facilement testé, et voici la raison: Quand foo
son premier appel, la variable statique x est initialisée à 5. Ensuite, elle est 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 qui a été affectée à x la dernière fois. L'exécution se déroule normalement, vous donnant la valeur 7.
6 7
x est une variable globale qui n'est visible que depuis foo (). 5 est sa valeur initiale, telle qu'elle est stockée dans la section .data du code. Toute modification ultérieure écrase la valeur précédente. Il n'y a pas de code d'affectation généré dans le corps de la fonction.
6 et 7 Parce que la variable statique ne s'initialise qu'une seule fois, Donc 5 ++ devient 6 au 1er appel 6 ++ devient 7 au 2ème appel Remarque - lorsque le 2ème appel se produit, la valeur x est 6 au lieu de 5 car x est une variable statique.
En C ++ 11 au moins, lorsque l'expression utilisée pour initialiser une variable statique locale n'est pas une 'constexpr' (ne peut pas être évaluée par le compilateur), l'initialisation doit se produire 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 à son tour nécessite une variable booléenne locale. J'ai compilé un tel exemple et vérifié que cela est vrai en voyant le code d'assemblage. L'exemple peut être comme ceci:
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 au chargement du programme en utilisant une valeur stockée par le compilateur dans le code d'assemblage de sortie.