W języku C zakres pamięci zmiennych określa, gdzie są przechowywane dane, jak długo są dostępne i która część kodu może je wywoływać. Historycznie słowa kluczowe auto (domyślnie dla zmiennych lokalnych), static (zachowuje wartość między wywołaniami, często używane do przechowywania stanu) oraz extern (deklaruje zmienną zdefiniowaną gdzie indziej) zostały wprowadzone, aby kontrolować zakres widoczności i czas życia zmiennych.
Problem — nieprawidłowe zrozumienie tego, gdzie i jak długo żyje zmienna, może prowadzić do błędów dostępu, wycieków pamięci i trudności w czytaniu kodu. Na przykład błędne oczekiwanie, że lokalna zmienna static będzie tworzona ponownie przy każdym wywołaniu funkcji, lub odwrotnie — że zmienna auto zachowa wartość między wywołaniami.
Rozwiązanie — zawsze świadomie wybierać specyfikator pamięci i rozumieć jego konsekwencje:
Przykład użycia:
// main.c int global_var = 42; // ma domyślny zakres static, zewnętrzne linkowanie void func() { static int counter = 0; // żyje między wywołaniami auto int temp = 5; // lokalna, auto nie trzeba podawać counter++; printf("wywołanie #%d\n", counter); } extern int global_var;
Kluczowe cechy:
Po co w ogóle pisać auto, skoro zmienne są domyślnie auto?
Odpowiedź: W nowoczesnych wersjach C słowo kluczowe auto praktycznie nie jest używane jawnie — dla zmiennej lokalnej to specyfikator domyślny. W rzeczywistości, jego jawne pisanie nie przynosi żadnych korzyści.
Czy można użyć static wewnątrz funkcji, aby zadeklarować zmienną globalną?
Odpowiedź: Nie, static wewnątrz funkcji czyni zmienną lokalną, ale zachowującą stan między wywołaniami. Nie jest widoczna poza funkcją.
Przykład kodu:
void foo() { static int call_count = 0; // Nie jest globalna, ale żyje między wywołaniami call_count++; }
Co się stanie, jeśli zadeklaruję zmienną jako extern wewnątrz funkcji, ale nie zdefiniuję jej nigdzie?
Odpowiedź: Doprowadzi to do błędu łączenia (linker error), ponieważ zadeklarowano referencję do zmiennej globalnej, która nie istnieje.
W dużym projekcie zmienne-moduły były zadeklarowane jako extern w wszystkich plikach źródłowych, ale zapominali o zrobieniu definicji. W rezultacie — tajemnicze błędy linkowania, niejasne dla początkujących programistów.
Zalety:
Wady:
Ściśle definiowano zakresy widoczności: każda zmienna static tylko w potrzebnym module, globalne extern deklarowane w nagłówkach i definiowane w jednym miejscu.
Zalety:
Wady: