
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:
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:
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:
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ę.
Aby uzyskać wartość zmiennej, na jaką, pokazuje wskaźnik, musimy użyć operatora "*". Załóżmy, że mamy zmienną typu char:
Zmienna "cyfra" wynosi 1, tworzymy sobie wskaźnik do zmiennej char:
Teraz tworzymy inną zmienną typu char:
I tutaj nasze zadanie, jak przypisać zmiennej cyferka wartość zmiennej cyfra, używając wskaźnika?
Najpierw musimy wskaźnikowi przypisać adres zmiennej cyfra, innymi słowy: wskaźnik musi wskazywać zmienną cyferka. Teraz sedno sprawy:
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:
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.
Referencja jest odwrotnością wskaźnika. Jest to zmienna, która "podszywa się" pod inną zmienną. Oto jak deklarujemy zmienna referencyjną:
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":
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:
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ą.