> C++ wskaźniki Dane: Iwona Polak iwona.polak@us.edu.pl Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017
>??? Co to jest WSKAŹNIK? ++ wskaźniki 2 / 20
>??? Co to jest WSKAŹNIK? To po prostu ADRES pamięci, w której coś jest zapisane. Wskaźnik wskazuje na obiekt, na inną zmienną itd. ++ wskaźniki 2 / 20
>??? Co to jest WSKAŹNIK? To po prostu ADRES pamięci, w której coś jest zapisane. Wskaźnik wskazuje na obiekt, na inną zmienną itd. Jak rozpoznać wskaźnik? ++ wskaźniki 2 / 20
>??? Co to jest WSKAŹNIK? To po prostu ADRES pamięci, w której coś jest zapisane. Wskaźnik wskazuje na obiekt, na inną zmienną itd. Jak rozpoznać wskaźnik? * ++ wskaźniki 2 / 20
>??? Co to jest WSKAŹNIK? To po prostu ADRES pamięci, w której coś jest zapisane. Wskaźnik wskazuje na obiekt, na inną zmienną itd. Jak rozpoznać wskaźnik? * * * * * * * * * * * * * * * * * * * C++ wskaźniki 2 / 20
> Organizacja pamięci operacyjnej C++ wskaźniki 3 / 20
> Deklaracja wskaźnika int *wsk; int* wsk; int * wsk; ++ wskaźniki 4 / 20
> Deklaracja wskaźnika int *wsk; int* wsk; int * wsk; UWAGA! int* a, b; ++ wskaźniki 4 / 20
> Deklaracja wskaźnika int *wsk; int* wsk; int * wsk; UWAGA! int* a, b; // a jest wskaźnikiem, b jest zwykłą zmienną int *a; // równoważne powyższemu int b; ++ wskaźniki 4 / 20
> Deklaracja wskaźnika int *wsk; int* wsk; int * wsk; UWAGA! int* a, b; // a jest wskaźnikiem, b jest zwykłą zmienną int *a; // równoważne powyższemu int b; A gdy chcemy dwa wskaźniki w jednej deklaracji: int *a, *b; Ważne! Każdy wskaźnik na coś wskazuje! Nawet jeśli nic nie zostało mu przypisane! C++ wskaźniki 4 / 20
> Użycie Wskaźnik musi mieć podany typ, na jaki wskazuje. ++ wskaźniki 5 / 20
> Użycie Wskaźnik musi mieć podany typ, na jaki wskazuje. 1. deklaracja zmiennej całkowitoliczbowej ++ wskaźniki 5 / 20
> Użycie Wskaźnik musi mieć podany typ, na jaki wskazuje. 1. deklaracja zmiennej całkowitoliczbowej 2. deklaracja wskaźnika na int ++ wskaźniki 5 / 20
> Użycie Wskaźnik musi mieć podany typ, na jaki wskazuje. 1. deklaracja zmiennej całkowitoliczbowej 2. deklaracja wskaźnika na int 4. przypisanie do wskaźnika adresu zmiennej & ++ wskaźniki 5 / 20
> Użycie Wskaźnik musi mieć podany typ, na jaki wskazuje. 1. deklaracja zmiennej całkowitoliczbowej 2. deklaracja wskaźnika na int 4. przypisanie do wskaźnika adresu zmiennej & 5. wyłuskanie wartości, na którą wskazuje wskaźnik ++ wskaźniki 5 / 20
> Zrób to sam int jakasliczba = 10; int *jakiswskaznik; jakiswskaznik = &jakasliczba; cout << Adres zmiennej: << jakiswskaznik << endl; cout << Adres zmiennej: << &jakasliczba << endl; cout << Wartosc: << *jakiswskaznik << endl; cout << Wartosc: << jakasliczba << endl; C++ wskaźniki 6 / 20
> Cztery domeny zastosowania wskaźników Wskaźniki stosuje się w sytuacjach, gdy chodzi nam o: 1. ulepszenie pracy z tablicami, 2. funkcje mogące zmieniać wartość przysyłanych do nich argumentów, 3. dostęp do specjalnych komórek pamięci, 4. rezerwację obszarów pamięci. C++ wskaźniki 7 / 20
> Wskaźniki jako argumenty funkcji void funkcja(int *wskaznik) { *wskaznik = 50; // lub jakaś inna operacja } int main() {... int zmienna = 0; cout << zmienna; // 0 funkcja ( &zmienna ); cout << zmienna; // 50... } ++ wskaźniki 8 / 20
> Rodzaje wskaźników Typ wskaźnikowy Nazwa Dostęp Zmiana do pamięci adresu 1 typ* zwykły wskaźnik odczyt i zapis 2 const typ* zwykły wskaźnik tylko odczyt na stałą 3 typ* const stały wskaźnik odczyt i zapis 4 const typ* const stały wskaźnik tylko odczyt na stałą C++ wskaźniki 9 / 20
> Rodzaje wskaźników Typ wskaźnikowy Nazwa Dostęp Zmiana do pamięci adresu 1 typ* zwykły wskaźnik odczyt i zapis const typ* zwykły wskaźnik tylko odczyt na stałą 3 typ* const stały wskaźnik odczyt i zapis 4 const typ* const stały wskaźnik tylko odczyt na stałą C++ wskaźniki 9 / 20
> Rodzaje wskaźników Typ wskaźnikowy Nazwa Dostęp Zmiana do pamięci adresu 1 typ* zwykły wskaźnik odczyt i zapis 2 const typ* zwykły wskaźnik tylko odczyt na stałą typ* const stały wskaźnik odczyt i zapis 4 const typ* const stały wskaźnik tylko odczyt na stałą C++ wskaźniki 9 / 20
> Rodzaje wskaźników Typ wskaźnikowy Nazwa Dostęp Zmiana do pamięci adresu 1 typ* zwykły wskaźnik odczyt i zapis 2 const typ* zwykły wskaźnik tylko odczyt na stałą 3 typ* const stały wskaźnik odczyt i zapis const typ* const stały wskaźnik tylko odczyt na stałą C++ wskaźniki 9 / 20
> Ćwiczenia 1. Zadeklaruj wskaźnik na typ całkowity. Spróbuj go przypisać tak, aby wskazywał na typ double. 2. Zadeklaruj poprawny wskaźnik. Sprawdź, czy wyłuskuje wskazywaną wartość. Sprawdź, jakie operatory działają na wskaźnikach (dodaj wskaźniki, odejmij, dodaj/odejmij stałą wartość liczbową, pomnóż, itp.) C++ wskaźniki 10 / 20
> Wskaźnik uniwersalny Czy istnieje wskaźnik uniwersalny (na dowolny typ)? ++ wskaźniki 11 / 20
> Wskaźnik uniwersalny Czy istnieje wskaźnik uniwersalny (na dowolny typ)? TAK. ++ wskaźniki 11 / 20
> Wskaźnik uniwersalny Czy istnieje wskaźnik uniwersalny (na dowolny typ)? TAK. * Deklaracja: void *nazwa; * W deklaracji takiego wskaźnika nie podajemy typu, na jaki będzie on wskazywał. Pozwala nam to przypisać obiekt każdego typu. * Niemożliwe jest wówczas wykorzystanie operatorów wyłuskania * oraz -> bez odwoływania się do rzutowania, bo kompilator nie wie nic o typie wartości przechowywanej pod adresem wskazywanym przez wskaźnik uniwersalny. 3. C++ 4. C Programista jest odpowiedzialny za kontrolę typów! C++ wskaźniki 11 / 20
> Operacje na wskaźnikach Legalnymi operacjami arytmetycznymi na wskaźnikach są: 1. dodawanie i odejmowanie od nich liczb naturalnych daje to przesuwanie wskaźników, 2. odejmowanie dwóch wskaźników (pokazujących na tę samą tablicę), 3. porównywanie dwóch wskaźników (pokazujących na tę samą tablicę) ==!= < > <= >= 4. każdy wskaźnik można porównać z adresem 0/NULL wsk == 0; // lub: wsk == NULL; ++ wskaźniki 12 / 20
> Wskaźniki a struktury * Przy strukturach operator wyłuskania -> działa podobnie jak operator wyłuskania *, natomiast jest po prostu wygodniejszy i szybszy. * Po co więc nawiasy w linii 7? Nie lepiej *wsk.dzien = 5? * Operator -> pozwala również wywołać metodę w strukturze: int x = wsk->getdzien(); //równoważne (*wsk).getdzien(); ++ wskaźniki 13 / 20
> Wskaźniki a funkcje Nazwa funkcji jest jednocześnie jej ADRESEM. * Wskaźnik na funkcję różni się od zwykłego wskaźnika budową i faktem, że adres wskaźnika oznacza miejsce w pamięci, w którym rozpoczyna się kod funkcji. * Wskaźnik taki deklaruje się następująco: <typ> (*nazwa)( <parametry_funkcji> ); * Nie ma uniwersalnego wskaźnika na funkcję! 3. lub: int (*f)(int,int) = add; C++ wskaźniki 14 / 20
> Wskaźniki a tablice Nazwa tablicy jest jednocześnie ADRESEM jej zerowego elementu. tabint oraz &tabint[0] są sobie równoważne W C++ można stosować arytmetykę wskaźników (do wskaźnika dodawać i odejmować liczby całkowite). Kompilator sam pomnoży dodawaną liczbę przez rozmiar typu wskaźnika, aby dodać do adresu odpowiednią liczbę bajtów. C++ wskaźniki 15 / 20
> Nazwa tablicy a wskaźnik na jej początek C++ wskaźniki 16 / 20
> Wskaźnik to nie tablica! C++ wskaźniki 17 / 20
> Ćwiczenia 1. Korzystając z arytmetyki wskaźników napisać program wypełniający kwadratową tablicę kolejnymi liczbami naturalnymi po spirali, przykładowo dla wymiaru 5 winniśmy uzyskać: 2. Opracować funkcje, które obliczają sumę dwóch liczb rzeczywistych x i y typu double. Prototypy funkcji mają następującą postać: 2..1 double sum1 (double x, double y); // suma zwracana przez wartość funkcji 2..2 void sum2(double x, double y, double * z); // suma zwracana przez wskaźnik 2..3 void sum3(double x, double y, double& z); // suma zwracana przez referencję C++ wskaźniki 18 / 20
> Ćwiczenie int a[4]; for(int i = 0; i < 4; i++) a[i] = i*10; cout << 3[a] << endl; Czy to się skompiluje? C++ wskaźniki 19 / 20
> Ćwiczenie int a[4]; for(int i = 0; i < 4; i++) a[i] = i*10; cout << 3[a] << endl; Czy to się skompiluje? Dlaczego? C++ wskaźniki 19 / 20
> Ćwiczenie int a[4]; for(int i = 0; i < 4; i++) a[i] = i*10; cout << 3[a] << endl; Czy to się skompiluje? Dlaczego? Co zostanie wyświetlone? C++ wskaźniki 19 / 20
> Ćwiczenie int a[4]; for(int i = 0; i < 4; i++) a[i] = i*10; cout << 3[a] << endl; Czy to się skompiluje? Dlaczego? Co zostanie wyświetlone? Dlaczego? C++ wskaźniki 19 / 20
> Zadanie domowe 1. Poczytaj o listach jednokierunkowych, dwukierunkowych, cyklicznych, itp. 2. Jak deklarujemy i jak je używamy w C++? 3. Zaimplementuj użycie listy jednokierunkowej liczb całkowitych wraz z operacjami: 3..1 Dodawania do listy, 3..2 Usuwania elementu (o danej wartości), 3..3 Wyszukiwania, czy dany element znajduje się w liście, 3..4 Zliczania liczby elementów. ++ wskaźniki 20 / 20