Quando insegno C, a volte conto su GCC per fare la parte "convincente" di alcune regole. Ad esempio, non si dovrebbe considerare che una variabile locale su una funzione mantenga il valore tra le chiamate.Le variabili locali non sono statiche, ma perché ottengo questo comportamento?
GCC mi ha sempre aiutato a insegnare queste lezioni agli studenti, mettendo la spazzatura su variabili locali, in modo che capiscano cosa sta succedendo.
Ora, questo pezzo di codice mi sta causando sicuramente dei problemi.
#include <stdio.h>
int test(int x)
{
int y;
if(!x)
y=0;
y++;
printf("(y=%d, ", y);
return y;
}
int main(void)
{
int a, i;
for(i=0; i<5; i++)
{
a=test(i);
printf("a=%d), ", a);
}
printf("\n");
return 0;
}
L'output è:
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
Ma se io commento la riga:
/* printf("(y=%d, ", y); */
L'uscita diventano:
a=1), a=32720), a=32721), a=32722), a=32723),
compilo il codice utilizzando -Wall
passare, ma nessun avviso gs sono correlati all'uso di variabili locali senza inizializzarle.
C'è qualche interruttore GCC per causare un avviso o almeno per mostrare esplicitamente un po 'di spazzatura? Ho provato le opzioni di ottimizzazione, e che ha aiutato come output codice divenne simili:
$ gcc test.c -o test -Wall -Os
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -Ofast
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O0
$ ./test
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
$ gcc test.c -o test -Wall -O1
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O2
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O3
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
Ma y = 1 in tutti i casi è tipo di trucco. Lo standard è cambiato così le variabili locali sono ora inizializzate con zeri?
Non penso che C specifichi uno standard per l'intializzazione delle variabili. In effetti, penso che la memoria rimanga così com'è, quindi quando si aggiunge a y, il valore di y era lo stesso di prima, e quindi lo si incrementa. – Magn3s1um
La coincidenza è che la seconda chiamata alla funzione sta utilizzando lo stesso codice di blocco della RAM. –
Non penso che sia una coincidenza, dal momento che il compilatore collegherà y ad una certa regione di memoria che è relativa. Non cambia la relazione di y con il primo stack, quindi se lo stack precedente non aumenta di dimensioni, y sarà sempre nello stesso posto! – Magn3s1um