Cosa verrà stampato? 6 6 o 6 7? E perché?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Cosa verrà stampato? 6 6 o 6 7? E perché?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Risposte:
Ci sono due problemi qui, durata e portata.
L'ambito della variabile è dove il nome della variabile può essere visto. Qui, x è visibile solo all'interno della funzione foo ().
La durata di una variabile è il periodo in cui esiste. Se x fosse definito senza la parola chiave static, la durata sarebbe dall'ingresso in foo () al ritorno da foo (); quindi sarebbe reinizializzato a 5 su ogni chiamata.
La parola chiave static agisce per estendere la durata di una variabile alla durata del programma; es. l'inizializzazione avviene una sola volta e poi la variabile mantiene il suo valore - qualunque cosa sia diventata - su tutte le future chiamate a foo ().
Uscita : 6 7
Motivo : la variabile statica viene inizializzata solo una volta (a differenza della variabile automatica) e un'ulteriore definizione di variabile statica verrebbe ignorata durante il runtime. E se non viene inizializzato manualmente, viene inizializzato automaticamente dal valore 0. Così,
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
il compilatore fa in modo che l'inizializzazione della variabile statica non avvenga ogni volta che si immette la funzione
È lo stesso che avere il seguente programma:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Tutto ciò che la parola chiave statica fa in quel programma è che dice al compilatore (essenzialmente) "hey, ho una variabile qui che non voglio che nessun altro acceda, non dire a nessun altro che esiste".
All'interno di un metodo, la parola chiave static dice al compilatore come sopra, ma anche, "non dire a nessuno che esiste al di fuori di questa funzione, dovrebbe essere accessibile solo all'interno di questa funzione".
Spero che aiuti
x
in main; è globale. Nell'esempio originale x
era local to foo, visibile solo all'interno di quel blocco, il che è generalmente preferibile: se foo esiste per mantenerlo x
in modi prevedibili e visibili, lasciare che gli altri lo colpiscano è generalmente pericoloso. Come un altro vantaggio di mantenerlo nell'ambito di applicazione, foo()
mantiene anche la foo()
portabilità.
c
, quindi in questo contesto, il tuo esempio sarebbe illegale a livello globale. (C richiede inizializzatori costanti per le globali, C ++ no).
Una variabile statica all'interno di una funzione ha una durata finché il programma viene eseguito. Non verrà allocato ogni volta che la tua funzione viene chiamata e deallocata quando la tua funzione ritorna.
La dichiarazione di x
è dentro foo
ma l' x=5
inizializzazione avviene all'esterno di foo
!
Quello che dobbiamo capire qui è questo
static int x = 5;
non è lo stesso di
static int x;
x = 5;
Altre risposte hanno utilizzato le parole importanti qui, ambito e durata, e hanno sottolineato che l'ambito di x
è dal punto della sua dichiarazione nella funzione foo
fino alla fine della funzione foo
. Ad esempio, ho verificato spostando la dichiarazione alla fine della funzione e ciò rende x
non dichiarato nel filex++;
dichiarata nell'istruzione.
Quindi la parte static int x
(ambito) dell'istruzione si applica effettivamente dove l'hai letta, da qualche parte ALL'INTERNO della funzione e solo da lì in poi, non sopra di essa all'interno della funzione.
Tuttavia, la parte x = 5
(durata) dell'istruzione è l' inizializzazione della variabile e accade FUORI dalla funzione come parte del caricamento del programma. La variabile x
nasce con un valore di5
quando il programma viene caricato.
Ho letto questo in uno dei commenti: " Inoltre, questo non risolve la parte veramente confusa, che è il fatto che l'inizializzatore viene saltato nelle chiamate successive. " Viene saltato in tutte le chiamate. L'inizializzazione della variabile è al di fuori del codice funzione vero e proprio.
Il valore di 5 è teoricamente impostato indipendentemente dal fatto che foo venga chiamato o meno, sebbene un compilatore potrebbe ottimizzare la funzione se non la chiami da nessuna parte. Il valore di 5 dovrebbe essere nella variabile prima che venga chiamato foo.
Dentro foo
, la dichiarazionestatic int x = 5;
è improbabile che generi alcun codice.
Ho trovato l'indirizzo x
utilizzato quando ho inserito una funzione foo
in un mio programma, e poi (correttamente) ho intuito che la stessa posizione sarebbe stata utilizzata se avessi eseguito di nuovo il programma. La schermata parziale di seguito mostra che x
ha il valore 5
anche prima della prima chiamata a foo
.
L'output sarà 6 7
. Una variabile statica (sia all'interno di una funzione o meno) viene inizializzata esattamente una volta, prima che venga eseguita qualsiasi funzione in quell'unità di traduzione. Dopodiché, mantiene il suo valore finché non viene modificato.
Vadiklk,
Perché ...? Il motivo è che la variabile statica viene inizializzata solo una volta e mantiene il suo valore in tutto il programma. significa che puoi usare la variabile statica tra le chiamate di funzione. può anche essere usato per contare "quante volte viene chiamata una funzione"
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
e la risposta è 5 4 3 2 1 e non 5 5 5 5 5 5 .... (ciclo infinito) come ti aspetti. ancora una volta, la ragione è che la variabile statica viene inizializzata una volta, quando la prossima volta che viene chiamato main () non verrà inizializzata a 5 perché è già inizializzata nel programma. Quindi possiamo cambiare il valore ma non possiamo reinizializzarla. Ecco come funziona la variabile statica.
oppure puoi considerare come per l'archiviazione: le variabili statiche sono memorizzate nella sezione dati di un programma e le variabili che sono memorizzate nella sezione dati vengono inizializzate una volta. e prima dell'inizializzazione sono conservati nella sezione BSS.
A loro volta, le variabili Auto (locali) vengono memorizzate su Stack e tutte le variabili sullo stack vengono reinizializzate ogni volta che viene chiamata la funzione quando viene creato un nuovo FAR (record di attivazione della funzione).
va bene per una maggiore comprensione, fai l'esempio precedente senza "statico" e ti faccio sapere quale sarà l'output. Questo ti fa capire la differenza tra questi due.
Grazie Javed
Leggiamo solo l' articolo di Wikipedia sulle variabili statiche ...
Variabili locali statiche: le variabili dichiarate come statiche all'interno di una funzione sono allocate staticamente pur avendo lo stesso ambito delle variabili locali automatiche. Quindi qualunque valore la funzione inserisce nelle sue variabili locali statiche durante una chiamata sarà ancora presente quando la funzione viene chiamata di nuovo.
Otterrai 6 7 stampati come, come è facilmente testato, ed ecco il motivo: quando foo
viene chiamato per la prima volta, la variabile statica x viene inizializzata a 5. Quindi viene incrementata a 6 e stampata.
Ora per la prossima chiamata a foo
. Il programma salta l'inizializzazione della variabile statica e utilizza invece il valore 6 che è stato assegnato a x l'ultima volta. L'esecuzione procede normalmente, dandoti il valore 7.
6 e 7 Poiché la variabile statica viene inizializzata solo una volta, quindi 5 ++ diventa 6 alla prima chiamata 6 ++ diventa 7 alla seconda chiamata Nota: quando si verifica la seconda chiamata, il valore x è 6 invece di 5 perché x è una variabile statica.
Almeno in C ++ 11, quando l'espressione utilizzata per inizializzare una variabile statica locale non è un "constexpr" (non può essere valutato dal compilatore), l'inizializzazione deve avvenire durante la prima chiamata alla funzione. L'esempio più semplice consiste nell'usare direttamente un parametro per inizializzare la variabile statica locale. Pertanto il compilatore deve emettere codice per indovinare se la chiamata è la prima o meno, il che a sua volta richiede una variabile booleana locale. Ho compilato tale esempio e verificato che sia vero vedendo il codice dell'assembly. L'esempio può essere così:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
ovviamente, quando l'espressione è "constexpr", non è richiesta e la variabile può essere inizializzata al caricamento del programma utilizzando un valore memorizzato dal compilatore nel codice assembly di output.