6. Zmienne globalne i lokalne.

6.3. Obszar widoczności lokalnych zmiennych

W tym rozdziale omówimy sytuacje, kiedy lokalna zmienna może nie być widoczna dla programu. Takim pierwszym oczywistym przypadkiem jest błąd w kodzie źródłowym, kiedy najpierw program musi skorzystać ze zmiennej, a dopiero potem ta zmienna jest tworzona (kod 1).

Kod 1
#property strict

void OnStart()
  {
   Print("LocalVariable = ",LocalVariable); /* błąd,
                                            kompilator nie widzi
                                            LocalVariable */

   int LocalVariable = 7;
  }

Tutaj niedoświadczony programista chciałby, aby najpierw została wyświetlona wartość nie istniejącej zmiennej LocalVariable, a dopiero potem została by ona utworzona. Kompilator wyświetli błąd: 'LocalVariable' - undeclared identifier, tj. 'LocalVariable' - nie zadeklarowany identyfikator. Te dwie instrukcje należy zamienić miejscami i problem zniknie.

Taki sam problem będzie miał miejsce jeśli wewnątrz jednego obszaru lokalnego zostanie utworzony drugi. W tym drugim obszarze program będzie musiał skorzystać ze zmiennej, która jednak zostanie utworzona później w pierwszym obszarze (kod 2).

Kod 2
#property strict

void OnStart()
  {
   bool LocalFlag = true;

   //--- granica obszaru lokalnego 'if', początek
   if(LocalFlag == true)          // ok, kompilator widzi LocalFlag
     {
      Print("LocalVariable = ",LocalVariable); /* błąd,
                                               kompilator nie widzi
                                               LocalVariable */

     }
   //--- granica obszaru lokalnego 'if', koniec

   int LocalVariable = 7;
  }

W tym kodzie w obszarze OnStart() najpierw następuje inicjalizacja zmiennej LocalFlag. Następnie operator if musi zobaczyć LocalFlag, aby móc sprawdzić warunek zapisany w jego nagłówku. W naszym przypadku jest ok, ponieważ zmienna ta została wcześniej zainicjowana. Dalej w obszarze utworzonym przez if za pomocą Print() program musi wyświetlić wartość nieistniejącej jeszcze w tym momencie zmiennej LocalVariable. Nieistniejącej, dlatego że jej inicjalizacja nastąpi dopiero później. Dla tego kodu kompilator wyświetli błąd: 'LocalVariable' - undeclared identifier, tj. 'LocalVariable' - nie zadeklarowany identyfikator.

Aby wyeliminować ten błąd zmienną LocalVariable należy zainicjalizować albo przed Print() w granicach if (kod 3) albo w obszarze OnStart() przed if (kod 4).

Kod 3
#property strict

void OnStart()
  {
   bool LocalFlag = true;
  
   if(LocalFlag == true)
     {
      int LocalVariable = 7;
      Print("LocalVariable = ",LocalVariable); /* ok,
                                               kompilator widzi
                                               LocalVariable */

     }
  }

Kod 4
#property strict

void OnStart()
  {
   bool LocalFlag     = true;
   int  LocalVariable = 7;
  
   if(LocalFlag == true)
     {
      Print("LocalVariable = ",LocalVariable); /* ok,
                                               kompilator widzi
                                               LocalVariable */

     }
  }

Omówmy kolejną sytuację, kiedy może wystąpić problem z widocznością zmiennej. Programista przygotował kod, gdzie inicjalizację zmiennej napisał przed jej wykorzystaniem (kod 5) i mogłoby się wydawać, że powinno być dobrze ale ... .

Kod 5
#property strict

void OnStart()
  {
   bool LocalFlag = true;

   //--- granica obszaru lokalnego 'if', początek
   if(LocalFlag == true)
     {
      int LocalVariable = 7;
     }
   //--- granica obszaru lokalnego 'if', koniec
  
   Print("LocalVariable = ",LocalVariable); /* błąd,
                                            kompilator nie widzi
                                            LocalVariable */

  }

Dla tego kodu kompilator wyświetli taki samy błąd jak i w przypadku kodów 1 i 2: 'LocalVariable' - undeclared identifier, tj. 'LocalVariable' - nie zadeklarowany identyfikator. Stanie się to tak dlatego, że ta zmienna została zainicjalizowana w obszarze utworzonym przez if i tylko tam jest ona dostępna dla programu.

Wytłumaczenie jest następujące. W momencie kiedy program dochodzi do operatora if i widzi, że warunek w jego nagłówku jest prawdziwy, to program tworzy nowy obszar lokalny. Dokonuje w nim inicjalizacji zmiennej LocalVariable, tj. w pamięci RAM rezerwuje miejsce i zapisuje tam wartość 7. Kiedy program dochodzi do końca tego obszaru, tj. do zamykającej klamry }, program niszczy ten obszar a wraz z nim i wszystkie zmienne tam utworzone. W naszym przypadku wychodząc z obszaru if z RAM usuwana jest LocalVariable i dlatego, kiedy program idzie do Print(), tj. wraca do poprzedniego obszaru OnStart(), ta zmienna już nie istnieje. Mówiąc inaczej czas życia zmiennej jest ograniczony czasem życia obszaru, gdzie została ona utworzona.


Zmienna jest widoczna (dostępna) dla programu tylko w tym obszarze lokalnym, w którym została utworzona.