Wskaźniki

Wskaźniki są cechą charakterystyczną dla języka C i C++, a zarazem są trudne do zrozumienia. Szczególnie, że w innych językach nie istnieje pojęcie wskaźnika, tak jak w C i C++. Żeby zrozumieć mechanizm wskaźników, trzeba wiedzieć jak działa pamięć w komputerze. Przypomnij sobie w lekcji o typach zmiennych, jak mówiliśmy o budowie pamięci. Pokazałem przykładowy fragmencik pamięci:

Zmienne zajmują komórki pamięci. Każda komórka w pamięci ma swój własny adres, czyli numer po którym procesor się do niej odwołuje.

Mając tę wiedzę, dopiero można zrozumieć czym jest wskaźnik. Wskaźnik to specjalna zmienna, która przechowuje adres komórki pamięci. Adres komórki pamięci to liczba, konkretniej numer komórki, więc wskaźnik przechowuje nic innego jak liczbę. Dodatkowo trzeba powiedzieć sobie o wielkości tej liczby. Otóż w systemach 32bitowych, adresy komórek pamięci, to liczby 32 bitowe, w systemach 64 bitowych, pamięć jest podpisana adresami o wartosciach 64 bitowych. Zobaczmy jak to wygląda w praktyce:

#include <iostream>


int main(int argc,char* argv[])
{
  int zmienna;
//tworzymy najzwyczajniejszą zmienną typu int

  int* wskaznik;
//tworzymy wskaźnik, będzie on zawierał adres zmiennej int

  wskaznik=&zmienna;
//wskaźnikowi przypisujemy adres zmiennej zmienna

  std::cout<<
"Adres zmiennej ktora pokazuje wskaznik: "
<<wskaznik<<std::endl;
  std::cout<<
"Wartosc zmiennej ktora pokazuje wskaznik: "
<<*wskaznik<<std::endl;
  system(
"PAUSE"
);
  return
0
;
}

Najpierw tworzymy zmienną typ int, potem tworzymy wskaźnik na zmienną typu int. Każdy wskaźnik może wskazywać tylko zmienną określonego typu. Jak widać wskaźnik tworzy się pisząc pomiędzy nazwą a typem znaczek *. Nie ma różnicy czy * napiszemy bliżej, nazwy czy typu, możemy nawet po środku napisać, już wspominałem, że spacja jest znakiem ignorowanym, ale oczywiście, słowa trzeba oddzielać od siebie spacjami, ale nie ma różnicy ile ich zrobimy. Po utworzeniu wskaźnika należy mu przypisać adres jakiejś zmiennej, oczywiście można od razu podczas tworzenia zainicjować wartość wskaźnika:

...
int* wskaznik=&zmienna;
...

Tutaj trzeba powiedzieć sobie o operatorze "&". Już wspominałem o nim podczas omawiania operatorów, ale teraz widzimy go w akcji. Służy on do wyłuskiwania adresu zmiennej po jego prawej stronie. Taki zapis jest niepoprawny:

...
int* wskaznik=zmienna;
//źle!

...

Nie możemy wskaźnikowi przypisać wartości zmiennej, czyli jakiejś liczby, tylko musimy przypisać adres, tej zmiennej, używając operatora "&". Mam nadzieje, że zrozumiałeś, bo mi temat wskaźników to nie przychodził łatwo.

Wracając do omawiania programu, dalej mamy taką linijkę.

...
std::cout<<
"Wartosc zmiennej ktora pokazuje wskaznik: "
;
std::cout<<*wskaznik<<std::endl;
...

Aby uzyskać wartość zmiennej, na jaką, pokazuje wskaźnik, musimy użyć operatora "*". Załóżmy, że mamy zmienną typu char:

...
char cyfra=
1
;
...

Zmienna "cyfra" wynosi 1, tworzymy sobie wskaźnik do zmiennej char:

...
char* wskaznik;
...

Teraz tworzymy inną zmienną typu char:

...
char cyferka;
...

I tutaj nasze zadanie, jak przypisać zmiennej cyferka wartość zmiennej cyfra, używając wskaźnika?

...
wskaznik=&cyfra;
...

Najpierw musimy wskaźnikowi przypisać adres zmiennej cyfra, innymi słowy: wskaźnik musi wskazywać zmienną cyferka. Teraz sedno sprawy:

...
cyferka=*wskaznik;
...

Zmiennej cyferka przypisujemy wartość tego, na co wskazuje wskaźnik. Wskaźnik jest adresem zmiennej cyfra, operator * zwraca wartość tego, na co pokazuje wskaźnik, czyli tego co jest pod adresem wskaznik, a pod adresem wskaźnika jest wartość cyfra, więc uzyskamy wartość zmiennej cyfra. Wiem, że to skomplikowane, co napisałem, ale prościej nie potrafię.

We wcześniejszym programie, linijka:

...
std::cout<<
"Wartosc zmiennej ktora pokazuje wskaznik: "
;
std::cout<<*wskaznik<<std::endl;
...

Pokazuje wartość, na którą pokazuje wskaźnik, czyli wartość zmiennej zmienna.

Podsumujmy:
wskaznik- jest to adres zmiennej
*wskaznik- jest to wartość tego, na co wskazuje wskaźnik
&zmienna- jest to adres zmiennej zmienna

Jeszcze może powiem słówko na temat samego adresu zmiennej, a jest to porostu jakaś liczba, w systeamach 32-u bitowych liczba 32 bitowa.

Referencje

Referencja jest odwrotnością wskaźnika. Jest to zmienna, która "podszywa się" pod inną zmienną. Oto jak deklarujemy zmienna referencyjną:

...
int zmienna;
//zwykła zmienna int

int& referencja=zmienna;
//zmienna referencyjna

...

Podczas deklaracji takiej zmiennej, trzeba ją od razu zainicjować. Tak, więc czym jest zmienna referencja? Odpowiedź pewnie cię zdziwi. Otóż referencja jest tym samym, co zmienna "zmienna". Jak już wcześniej powiedziałem, zmienna referencyjna podszywa się pod inną zmienną, w naszym przypadku zmienna referencja jest tą samą zmienną co "zmienna". Zmienna referencyjna nie zajmuje żadnego miejsca w pamięci. To tak jakbyśmy zmiennej zmienna nadali dwie nazwy.

Zmienne "zmienna" i "referencja" tak naprawdę są tą samą zmienną. Gdy zmieniamy wartość jednej z nich, automatycznie zmienia się wartość drugiej, ponieważ są one tymi samymi zmiennymi.

Spójrzmy na przykład, udowodni on, ze zmienna referencyjna jest pod tym samym adresem, co zmienna "zmienna":

#include <iostream>


int main(int argc,char* argv[])
{
  int zmienna;
  int& referencja=zmienna;
//tworzymy zmienną referencją
  //teraz pokażemy adresy w pamięci obu zmiennych

  std::cout<<
"Adres zmiennej zmienna: "
<<&zmienna<<std::endl;
  std::cout<<
"Adres zmiennej referencyjnej referencja: "
<<&referencja<<std::endl;
  system(
"PAUSE"
);
  return
0
;
}


Teraz skompiluj i sprawdź. Oba adresy powinny być takie same. Potwierdza to, że obie zmienne, są tą samą zmienną w pamięci.

Teraz napiszmy program, który potwierdzi, że gdy zmienimy wartość jednej z nich zmienia się także druga:

#include <iostream>


int main(int argc,char* argv[])
{
  int zmienna;
  int& referencja=zmienna;
//tworzymy zmienną referencją

  std::cout<<
"Podaj wartosc zmiennej zmienna:\n"
;
  std::cin>>zmienna;
  std::cout<<
"Wyswietl wartosc zmiennej zmienna: "
<<zmienna<<std::endl;
  std::cout<<
"Wyswietl wartosc zmiennej referencja: "
<<referencja<<std::endl;
  std::cout<<
"Podaj wartosc zmiennej referencja:\n"
;
  std::cin>>referencja;
  std::cout<<
"Wyswietl wartosc zmiennej zmienna: "
<<zmienna<<std::endl;
  std::cout<<
"Wyswietl wartosc zmiennej referencja: "
<<referencja<<std::endl;
  system(
"PAUSE"
);
  return
0
;
}

Ten program jest dowodem na to, że modyfikując jedną ze zmiennych, zmieniamy obie, ponieważ obie są tak naprawdę jedną zmienną, tylko inaczej się nazywają.

Wejść na stronę:     Ilość osób online:
Prawa autorskie © 2008 crayze. Wszelkie prawa zastrzeżone.
crayze7@gmail.com