Twoja zmienna d
zazwyczaj nie jest usuwana ze stosu. Nawiasy klamrowe nie oznaczają ramki stosu. W przeciwnym razie nie byłbyś w stanie zrobić czegoś takiego:
char var = getch();
{
char next_var = var + 1;
use_variable(next_char);
}
Jeśli nawiasy klamrowe spowodowałyby prawdziwy stos push / pop (jak wywołanie funkcji), powyższy kod nie zostałby skompilowany, ponieważ kod wewnątrz nawiasów nie byłby w stanie uzyskać dostępu do zmiennej, var
która znajduje się poza nawiasami klamrowymi (tak jak pod- funkcja nie ma bezpośredniego dostępu do zmiennych w funkcji wywołującej). Wiemy, że tak nie jest.
Szelki kręcone są po prostu używane do określania zakresu. Kompilator potraktuje każdy dostęp do zmiennej "wewnętrznej" spoza otaczających nawiasów jako nieprawidłowy i może ponownie wykorzystać tę pamięć do czegoś innego (jest to zależne od implementacji). Jednak nie można go zdjąć ze stosu, dopóki funkcja otaczająca nie powróci.
Aktualizacja: Oto, co ma do powiedzenia specyfikacja C. Odnośnie obiektów z automatycznym czasem przechowywania (sekcja 6.4.2):
W przypadku obiektu, który nie ma typu tablicy o zmiennej długości, jego okres istnienia rozciąga się od wejścia do bloku, z którym jest skojarzony, do momentu, gdy wykonanie tego bloku i tak zakończy się.
Ta sama sekcja definiuje termin „żywotność” jako (wyróżnienie moje):
Czas życia obiektu to część wykonywania programu, podczas której gwarantowane jest zarezerwowanie dla niego miejsca. Obiekt istnieje, ma stały adres i zachowuje swoją ostatnio zapisaną wartość przez cały okres jego istnienia. Jeśli odniesienie do obiektu jest poza jego okresem istnienia, zachowanie jest niezdefiniowane.
Kluczowym słowem jest tutaj oczywiście „gwarantowana”. Po wyjściu z zakresu wewnętrznego zestawu nawiasów klamrowych okres istnienia tablicy dobiega końca. Pamięć może być dla niego przydzielona lub nie (Twój kompilator może ponownie wykorzystać to miejsce na coś innego), ale wszelkie próby uzyskania dostępu do tablicy wywołują niezdefiniowane zachowanie i powodują nieprzewidywalne rezultaty.
Specyfikacja C nie zawiera pojęcia ramek stosu. Mówi tylko o tym, jak zachowa się wynikowy program i pozostawia szczegóły implementacji kompilatorowi (w końcu implementacja wyglądałaby zupełnie inaczej na procesorze bez stosu niż na procesorze ze stosem sprzętowym). W specyfikacji C nie ma nic, co określa, gdzie ramka stosu będzie się kończyć lub nie. Jedyny prawdziwy sposobem, aby to wiedzieć, jest skompilowanie kodu na konkretnym kompilatorze / platformie i zbadanie wynikowego zestawu. Obecny zestaw opcji optymalizacyjnych Twojego kompilatora prawdopodobnie również odegra w tym rolę.
Jeśli chcesz mieć pewność, że tablica d
nie zajmuje już pamięci podczas działania kodu, możesz albo przekonwertować kod w nawiasach klamrowych na osobną funkcję, albo jawnie malloc
i free
pamięć, zamiast korzystać z automatycznego przechowywania.