c++
Wskaźniki mają jeszcze jedną przydatną cechę. W dowolnym momencie można zmienić typ wskaźnika. Robi się to za pomocą operatora rzutowania.
Najpierw zdefiniujemy sobie wsk_uniwersalny mogący pokazywać na liczby long. Następnie zdefiniujemy sobie trzy zmienne różnych typów. Ustawimy nasz wskaźnik na zmienną typu long. Wszystko jest w porządku. Zarówno zmienna, jak i wskaźnik są tego samego typu. Jak myślisz, co się stanie, gdy podstawimy do wskaźnika zmienną innego typu? Kompilator wywali błąd
Jednakże są sytuacje kiedy zmiana typu wskaźnika jest przydatna. Zmiana, czyli konwersja zachodzi za sprawą operatora rzutowania. Taki operator, to nic innego, jak zwykły nawias stawiany przed konwertowanym typem, a zawierający określenie nowego typu.
(int *)wsk_uniwersalny; spowoduje, że wsk_uniwersalny, który był wskaźnikiem pokazującym na liczby long staje się wskaźnikiem do liczb Pamiętaj tylko, że w nawiasie należy jeszcze podać gwiazdkę. Informuje ona, że chodzi o wskaźnik, a nie o zmienną.
Stałe definiowaliśmy poprzedzając je słówkiem const. Stałe można było inicjalizować tylko podczas ich definicji. Wartość raz nadana nie mogła ulec zmianie. Wskaźnikami również można tak manipulować.
ć ż ś Zdefiniowaliśmy sobie dwie zmienne: x i y. Obie typu float. Następnie definiujemy stały wskaźnik wsk mogący pokazywać na obiekty typu float i od razu go inicjalizujemy (inicjalizacja stałego wskaźniku musi nastąpić podczas jego definiowania) stałego wskaźnika nie można ustawić nawet na ten sam obiekt - linijka: wsk = &x. jedynym miejscem ustawienia wskaźnika jest miejsce jego definicji. Co za tym idzie żadne operacja przesuwania typu wsk++; wsk--; wsk += 3; etc. także nie zadziałają!
Mamy zwykłą zmienną x typu float oraz wskaźnik wsk ustawiony na niej. Sam wskaźnik posiada jednak pewne ograniczenie. Nie może bowiem modyfikować wartości obiektu, na który wskazuje. Sam obiekt oczywiście nie musi być stałą, co widać w przykładzie.
wskaźnikiem nie można poruszać, ani przestawiać, a dodatkowo nie można zmieniać wartości obiektu, na który wskazuje. Dla formalności przykład takiego wskaźnika: float pi = 3.14; const float * const wsk = π
Zmienne przekazujemy do funkcji przez wartość referencję.
Skoro funkcja pobiera jako argument wskaźnik na zmienną, to faktycznie pobiera adres zmiennej. A jeśli pobrany został adres zmiennej, funkcja działa bezpośrednio na zmiennej, nie na jej kopii. Nasza zdefiniowana funkcja działa więc tak samo jak funkcja w postaci: Zalecamy jednak przekazywanie funkcji argumentów będących wskaźnikami, ponieważ mamy wtedy pewność, że taka funkcja będzie działała na oryginalnych zmiennych
Zacznijmy od programu, dzięki któremu zobaczymy, jak ułożone są w pamięci kolejne elementy tablicy: ą ę Zauważ, że w pętli nie wyświetlamy wartości elementów, lecz adresy komórek, w których te wartości będą przechowywane.
Jeśli znamy adres pierwszego elementu tablicy i wiemy, ile bajtów zajmuje zmienna tego samego typu, co elementy tablicy, to łatwo obliczymy adres komórki, pod którym znajdziemy zapisaną wartość dowolnego n-tego elementu tablicy. Jeśli wiec ustawimy wskaźnik na pierwszy element tablicy, to inkrementując go, będziemy się przesuwać do kolejnych jej elementów. Aby znaleźć adres pierwszego elementu tablicy, wystarczy odwołać się do nazwy tablicy.
W języku C+ + nazwa tablicy jest jednocześnie wskaźnikiem do jej pierwszego elementu. Oznacza to, że tab jest tym samym, co &tab [ 0 ]
Wynika stąd, że instrukcje są równoważne. Dlatego gdy przekazywaliśmy wywoływanej funkcji nazwę tablicy, to przekazywaliśmy wskaźnik do jej pierwszego elementu, czyli adres w pamięci, pod którym znajdowała się tablica. Funkcja działała więc na oryginalnej tablicy, a nie na jej kopii.
Zdefiniujemy wskaźnik na zmienną będącą liczbą całkowitą Ustawimy go na pierwszym elemencie tablicy, a następnie będziemy go tylko przesuwać wzdłuż tablicy, bez potrzeby odnajdywania za każdym razem początku tablicy.
ź ź ź ść ę ź ść ź ę ę ź