Najbardziej podstawowa różnica dotyczy zakresu.
W pierwszym przypadku deklarujesz zmienną globalną. Jest to zmienna, która jest dostępna w każdym zakresie po jej zdefiniowaniu.
void setup()
{
Serial.begin(9600);
}
void inc();
int count = 0;
void loop()
{
Serial.println(count);
count++;
inc();
delay(500);
}
void inc() //Can edit the value of count
{
count=count+1;
};
W drugim przypadku deklarujesz zmienną statyczną o zasięgu lokalnym. Zmienna będzie trwała przez cały czas działania programu podobnie jak zmienne globalne, ale będzie dostępna tylko w bloku kodu, w którym została zadeklarowana. Jest to ten sam przykład, z tylko jedną zmianą. count
jest teraz zadeklarowany w środku jako zmienna statyczna loop
.
void inc();
void loop()
{
static int count = 0;
Serial.println(count);
count++;
inc();
delay(500);
}
To się nie skompiluje, ponieważ funkcja inc()
nie ma dostępu do count
.
Zmienne globalne, choć z pozoru przydatne, wiążą się z pewnymi pułapkami. Mogą nawet powodować szkody, jeśli chodzi o pisanie programów, które mogą wchodzić w interakcje z fizycznym otoczeniem. To bardzo prosty przykład czegoś, co może się wydarzyć, gdy tylko programy zaczną się powiększać. Funkcja może przypadkowo zmienić stan zmiennej globalnej.
void setup()
{
Serial.begin(9600);
}
void another_function();
int state=0;
void loop()
{
//Keep toggling the state
Serial.println(state);
delay(250);
state=state?0:1;
//Some unrelated function call
another_function();
}
void another_function()
{
//Inadvertently changes state
state=1;
}
Takie przypadki są bardzo trudne do debugowania. Tego rodzaju problem można jednak łatwo wykryć, po prostu używając zmiennej statycznej.
void setup()
{
Serial.begin(9600);
}
void another_function();
void loop()
{
static int state=0;
//Keep toggling the state
Serial.println(state);
delay(250);
state=state?0:1;
//Some unrelated function call
another_function();
}
void another_function()
{
//Results in a compile time error. Saves time.
state=1;
}
Obie zmienne są statyczne - zachowują się przez całą sesję wykonania. Globalny jest widoczny dla każdej funkcji, jeśli deklaruje - nie definiuje - globalny lub jeśli funkcja jest zgodna z definicją w tej samej jednostce kompilacji (plik + zawiera).
Przeniesienie definicji funkcji
count
do wewnątrz ogranicza zarówno jej widoczność do najbliższego zbioru{}
esów, jak i daje jej czas życia wywołania funkcji (jest tworzony i niszczony, gdy funkcja jest wprowadzana i opuszczana). Zadeklarowanie gostatic
również daje czas życia sesji wykonawczej, który istnieje od początku do końca sesji wykonawczej, utrzymując się między wywołaniami funkcji.BTW: bądź ostrożny przy używaniu zainicjowanej statyki w obrębie funkcji, ponieważ widziałem, że niektóre wersje kompilatora gnu źle to robią. Automatyczna zmienna z inicjatorem powinna być tworzona i inicjalizowana przy każdym wpisie funkcji. Statyczny z inicjatorem powinien zostać zainicjowany tylko raz, podczas konfiguracji wykonywania, zanim nadana zostanie kontrola main () (podobnie jak globalna). Miałem ponownie zainicjowaną lokalną statykę przy każdym wpisie funkcji, jakby to była automatyka, co jest nieprawidłowe. Przetestuj swój kompilator, aby się upewnić.
źródło
extern
?Zgodnie z dokumentacją Atmela: „Jeśli zostanie zadeklarowana zmienna globalna, unikalny adres w pamięci SRAM zostanie przypisany do tej zmiennej w czasie połączenia programu”.
Pełna dokumentacja znajduje się tutaj (Wskazówka nr 2 dotycząca zmiennych globalnych): http://www.atmel.com/images/doc8453.pdf
źródło