Edytuj stronę Odnośniki Fold/unfold all ODT export Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić. ====== Wskaźniki ====== Wskaźnik (//pointer//) to adres, który określa jednoznacznie pozycję danych w pamięci komputera. Każda zmienna zajmuje określone miejsce w pamięci i jest umiejscowiona w pamięci pod pewnym adresem. Tak jak adres na kopercie listu wskazuje jednoznacznie lokalizację adresata tak wskaźnik pokazuje miejsce w pamięci, gdzie możemy odnaleźć wskazywaną zmienną. Adres zmiennej uzyskujemy za pomocą operatora referencji '&'. **Adres zmiennej i operator ''&''** Operator referencji ''&'' zwraca adres zmiennej. Jest to operator jednoargumentowy, tzn. działa na jedną wartość stojącą z prawej strony, np.: ''&x'' wyznacza adres zmiennej ''a''. <file C wsk1.c> #include<stdio.h> int main() { int a = 42; printf("adres zmiennej a %p\n", &a); } </file> Przykładowy wynik działania programu: <code> adres zmiennej a 0x7fff8e6a47e4 </code> Adres jest dodatnią liczbą całkowitą, którą wygodnie jest przedstawiać w systemie szesnastkowym. Jednak zazwyczaj nie ma potrzeby prezentowania tej wartości. Możemy taki adres przypisać do zmiennej wskaźnikowej i korzystać z tej zmiennej gry potrzebujemy dostępu do wskazywanego obszaru pamięci. **Deklaracja zmiennej wskaźnikowej ** Zmienna wskaźnikowa to zmienna, która przechowuje adres do zmiennej pewnego typu. W poniższym przykładzie znajduje przykład który zawiera deklarację zmiennej wskaźnikowej ''w'', która będzie przechowywała adres zmiennej typu ''int''. W instrukcji ''w = &a'' następuje przypisanie wartości ''&a'' do zmiennej ''w''. <file C wsk2.c> #include<stdio.h> int main() { int a = 42; int *w; w = &a; printf("w = %p\n", w); printf("adres zmiennej a %p\n", &a); } </file> Przykładowy wynik działania programu: <code> w = 0x7fff0c2c954c adres zmiennej a 0x7fff0c2c954c </code> W podobny sposób deklaruje się zmienne wskaźnikowe, które mogą przechowywać adresy zmiennych dowolnego typu a nawet adresy innych zmiennych wskaźnikowych. Przykłady deklaracji zmiennych wskaźnikowych: <code C> int *a; // wskaźnik zmiennej typu int float *b; // wskaźnik zmiennej typu float char *c // wskaźnik zmiennej typu char int *d[10]; // tablica 10-cio elementowa wskaźników typu int float **e; // wskaźnik zmiennej typu float* (wskaźnik do wskaźnika) </code> **Dostęp do adresu - operator ''*''** Operator dereferencji ''*'' służy do wydobycia wskazanej przez wskaźnik wartości. To również operator jednoargumentowy a instrukcja ''*x'' zwraca wartość wskazywaną, przez adres zawarty w zmiennej ''x'', tzn. zmienna ''x'' musi być zmienną wskaźnikową i zawiera poprawny adres pewnej innej zmiennej. Zwróć uwagę, że symbol ''*'' używany jest również jako operator mnożenia '' x * y '', jednak mnożenie jest operacją na dwóch argumentach, zaś operator dereferencji działa zawsze na jedną wartość. Operator dereferencji ''*'' udostępnia wartość z danego adresu, dzięki czemu możemy nie tylko odczytać wartość wskazywanej zmiennej ale także zmodyfikować jej wartość. Przykład: <file C wsk3.c> #include<stdio.h> int main() { int a = 42; int *w; w = &a; printf("a = %d\n", a); printf("*w = %d\n", *w); *w = 13; printf("a = %d\n", a); printf("*w = %d\n", *w); } </file> Wynik działania programu: <code> a = 42 *w = 42 a = 13 *w = 13 </code> **Uwaga:** uważaj na to aby zmienna wskaźnikowa zawsze zawierała poprawny adres. Sprawdź, co się stanie jeżeli w powyższym przykładzie usuniemy instrukcję ''w = &a''. Brak przypisania poprawnego adresu w zmiennej ''w'' doprowadzi do katastrofy w momencie wykonania instrukcji ''*w = 13''. **Wskaźnik argumentem funkcji ** Jednym z najważniejszych zastosowań wskaźników jest ich wykorzystanie w argumentach funkcji. Adres zmiennej przekazany w argumencie funkcji pozwala tej funkcji zmodyfikować wartość wskazywanej zmiennej, tzn. funkcja jest w stanie podstawić nową wartość do wskazywanej zmiennej. Poniższy przykład prezentuje definicję funkcji ''zwieksz'', która przyjmuje w argumencie wskaźnik zmiennej (''int * a'') a następnie odnosząc się przez dany adres zwiększa wartość o 1. <file C wsk4.c> #include<stdio.h> void zwieksz(int *a) { *a = *a + 1; } int main() { int a = 1; zwieksz( &a ); printf("a = %d\n", a); } </file> Wynik działania programu: <code> a = 2 </code> W taki sam sposób działa funkcja ''scanf("%d", &x)'', która w drugim argumencie MUSI mieć adres zmiennej ''x'' do której podstawi wartość wczytaną z terminala. ===== Ćwiczenie - zamiana wartości ===== Napisz funkcję ''zamień()'', która zamienia wartości 2 zmiennych podanych w argumentach.\\ Przetestuj działanie funkcji w programie, który wczyta 2 liczby do zmienneych a nastepnie zamieni ich wartości korzystając z funkcji ''zamień()'' ===== Ćwiczenie - pierwiastki równania kwadratowego ===== Zaimplementuj funkcję o nazwie ''**pierwiastki**'', która wyznacza miejsca zerowe równania kwadratowego. Parabola jest określona przez trzy wartości rzeczywiste ''a'', ''b'' i ''c'' równaniem \[ f(x) = ax^2 + bx + c \] Parabola może posiadać dwa miejsca zerowe, jedno miejsce zerowe lub może nie posiadać miejsc zerowych. Zadana funkcja ''parabola'' zwraca informację o liczbie miejsc zerowych (0, 1 lub 2) oraz dwie wartości rzeczywiste ''x1'' oraz ''x2'' stanowiące miejsca zerowe. \\ **Argumenty funkcji pierwiastki**: liczby rzeczywiste ''a'', ''b'', ''c'' definiujące równanie kwadratowe oraz dwa adresy (wskaźniki) ''x1'' oraz ''x2'', pod które zostaną wstawione wartości obu miejsc zerowych. W przypadku braku miejsc zerowych, zmienne wskazywane przez wskaźniki nie są modyfikowane. \\ **Wartość zwracana funkcji**: liczba całkowita (0, 1 lub 2) określająca liczbę miejsc zerowych równania kwadratowego Napisz program, który pobierze od użytkownika 3 liczby rzeczywiste ''a'', ''b'' oraz ''c'' a następnie, korzystając z funkcji ''pierwiastk()'' wyznaczy miejsca zerowe równania kwadratowego zdefiniowanego podanymi współczynnikami. Wynikiem działania programu jest komunikat informujący o liczbie miejsc zerowych oraz wartości tych miejsc zerowych. **Przykład działania programu** <code> Podaj wsp. paraboli a, b i c : 1 1 1 Brak miejsc zerowych </code> <code> Podaj wsp. paraboli a, b i c : 1 -4 4 Jedno miejsce zerowe: 2.000000 </code> <code> Podaj wsp. paraboli a, b i c : 1 0 -4 Dwa miejsca zerowe: x1=2.000000, x2=-2.000000 </code> {{page>.:zadania:07_zad_rzut&nofooter}} Rozwiązanie (plik źródłowy) umieść w Moodle pod adresem https://moodle.umk.pl/WFAIIS/mod/assign/view.php?id=7533