Deklaracja i inicjalizacja zmiennych to kamień węgielny języka C z bardzo surowymi i czasami niewidocznymi zasadami. To, jak i gdzie zadeklarujesz zmienną, wpłynie nawet na jej wartość początkową (dotyczy to inicjalizacji) oraz powiązanie z obiektem pamięci (dotyczy to deklaracji i definicji).
C sięga czasów, gdy optymalizacja pamięci była priorytetem. Programiści musieli samodzielnie deklarować i inicjalizować zmienne, w przeciwnym razie zachowanie programu stawało się nieprzewidywalne. W nowoczesnych kompilatorach C nawet małe odchylenia prowadzą do błędów linkera lub niejawnej inicjalizacji „śmieci”.
Podstawowe błędy:
Przykład kodu:
#include <stdio.h> int global_var; // definicja, auto-inicjalizacja = 0 static int static_global_var; // static-file, auto-inicjalizacja = 0 extern int extern_var; // deklaracja, definicja gdzie indziej void foo() { int local_var; // automatyczna, nieinicjalizowana -> śmieci static int static_local_var; // static, auto-inicjalizowana na 0 }
Kluczowe cechy:
1. Zmienne automatyczne (lokalne bez static i extern) są automatycznie inicjalizowane przez kompilator do 0?
Nie, zawierają śmieci. Ich wartość nie jest zdefiniowana, używanie przed inicjalizacją to błąd.
2. Czy można wielokrotnie definiować zmienną z extern w różnych plikach?
Nie, potrzebna jest jedna definicja, reszta — deklaracje przez extern, w przeciwnym razie linker wygeneruje błąd „wielokrotna definicja” lub „nieokreślony symbol”.
3. Czym różni się deklaracja funkcji od jej definicji?
Deklaracja — tylko prototyp (bez ciała); definicja — musi zawierać ciało funkcji. Dla zmiennych deklaracja przez extern nie rezerwuje pamięci, a dla funkcji obie formy są dozwolone.
Deklaracja globalnej zmiennej int counter; w dwóch plikach nagłówkowych. Projekt został zlinkowany z błędem wielokrotnej definicji.
Zalety:
Wady:
W nagłówku wpisano extern int counter;, definicję int counter = 0; — tylko w jednym pliku C.
Zalety:
Wady: