La variabile in d
genere non viene eliminata dallo stack. Le parentesi graffe non indicano una cornice di pila. Altrimenti, non saresti in grado di fare qualcosa del genere:
char var = getch();
{
char next_var = var + 1;
use_variable(next_char);
}
Se le parentesi graffe causassero un vero push / pop di stack (come farebbe una chiamata di funzione), il codice sopra riportato non verrebbe compilato perché il codice all'interno delle parentesi non sarebbe in grado di accedere alla variabile var
che vive al di fuori delle parentesi graffe (proprio come un sub- la funzione non può accedere direttamente alle variabili nella funzione chiamante). Sappiamo che non è così.
Le parentesi graffe vengono semplicemente utilizzate per lo scoping. Il compilatore considererà non valido qualsiasi accesso alla variabile "interna" dall'esterno delle parentesi graffe e potrà riutilizzare quella memoria per qualcos'altro (dipende dall'implementazione). Tuttavia, non può essere rimosso dallo stack fino a quando non viene restituita la funzione di chiusura.
Aggiornamento: ecco cosa dicono le specifiche C. Per quanto riguarda gli oggetti con durata di memorizzazione automatica (sezione 6.4.2):
Per un oggetto che non ha un tipo di array di lunghezza variabile, la sua durata si estende dall'entrata nel blocco a cui è associato fino a quando l'esecuzione di quel blocco non termina comunque.
La stessa sezione definisce il termine "vita" come (enfasi mia):
La durata di un oggetto è la parte dell'esecuzione del programma durante la quale è garantito che l'archiviazione ne sia riservata. Un oggetto esiste, ha un indirizzo costante e conserva il suo ultimo valore memorizzato per tutta la sua durata. Se si fa riferimento a un oggetto al di fuori della sua durata, il comportamento non è definito.
La parola chiave qui è, ovviamente, "garantita". Una volta che lasci l'ambito dell'insieme di parentesi graffe, la durata dell'array è finita. L'archiviazione può o meno essere allocata per esso (il compilatore potrebbe riutilizzare lo spazio per qualcos'altro), ma qualsiasi tentativo di accedere all'array invoca comportamenti indefiniti e porta a risultati imprevedibili.
La specifica C non ha nozioni di stack frame. Parla solo di come si comporterà il programma risultante e lascia i dettagli dell'implementazione al compilatore (dopotutto, l'implementazione sembrerebbe piuttosto diversa su una CPU stackless rispetto a una CPU con uno stack hardware). Non c'è nulla nelle specifiche C che impone dove un frame dello stack finirà o non finirà. L'unico vero modo per sapere è compilare il codice sul proprio compilatore / piattaforma particolare ed esaminare l'assembly risultante. Anche l'attuale set di opzioni di ottimizzazione del compilatore avrà un ruolo in questo.
Se si desidera assicurarsi che l'array d
non stia più esaurendo la memoria mentre il codice è in esecuzione, è possibile convertire il codice tra parentesi graffe in una funzione separata o esplicitamente malloc
e free
la memoria invece di utilizzare l'archiviazione automatica.