Opracowała: dr inż. Anna Dubowicka Uczelniane Centrum Komputerowe PK IX. Wskaźniki.(3 godz.) Wskaźnik jest zmienną, która zawiera adres innej. 1. Definiowanie wskaźników. typ * nazwa ; gdzie: znak * informuje nas, ze mamy do czynienia ze wskaźnikiem, typ informuje nas, ze wskaźnik ma służyć do pokazywania na zmienną określonego typu. int *w; Czytamy w jest wskaźnikiem do typu int, czyli w w możemy przechowywać adres jakiejś typu int. Typ wskaźnik do... jest typem pochodnym. Może być wskaźnikiem do wszystkich dotychczas poznanych typów (int, double, float, char, itp.). Wskaźnik zajmuje tyle bajtów, ile bajtów jest przeznaczonych na adresy w danym komputerze. Przykładowo dla komputerów 3- bitowych zajmuje 4 bajty. Wskaźnik zajmuje tyle samo bajtów bez względu na to, na jaki typ wskazuje.. Inicjalizacja wskaźników. Wskaźniki przed ich pierwszym użyciem powinny być ustawione. a) Wskaźnik można ustawić tak, by pokazywał na jakąś zmienną wstawiając do niego adres wybranej. Operatorem pozwalającym na odczytanie adresu jest & (apersand). Jest to operator prawostronnie łączny. double,*a; a=&; Po tej instrukcji zmienna a wskazuje na zmienną. b) Wskaźnik można ustawić również na to samo, na co pokazuje już inny wskaźnik. Jest to zwykła operacja przypisania wskaźników.
double,*a,*b; a=&; b=a; b wskazuje na tę samą zmienną co a, a wiec na zmienną. Wskaźnik może pokazywać również na tablicę, na ciąg znaków, na funkcję. Tymi przypadkami w tym momencie nie będziemy się zajmować. Mnemotechnicznie można zapamiętać, że &(apersand) zaczyna się na literę a jak adres. 3. Odwołanie się do obiektu, na który pokazuje wskaźnik. Do odwołania się do wskazywanej przez wskaźnik służy jednoargumentowy operator wskazania pośredniego gwiazdka (*). Jest to operator prawostronnie łączny. int k,*w; k=3; w=&k; printf( %d\n,*w); Gwiazdka w ostatniej instrukcji kieruje nas do wskazywanej przez w. Zmienna w wskazuje na zmienną k. Zatem od tej pory *w oznacza to samo co k,a więc program wydrukuje 3, czyli ostatnia instrukcja jest równoważna instrukcji printf( %d\n,k). Inny przykład: int k,i,*w; w=&k; k=1; i=k+5; lub równoważne i=*w+5; W obu instrukcjach i zostanie nadana wartość 6. Jeszcze zwróćmy uwagę na przykład następujący: double a,b; a=34; b=; b=a*(*(&b)); Gwiazdki są użyte w dwu znaczeniach:
gwiazdka w nawiasie oznacza wskazanie pośrednie a więc b, gwiazdka przed nawiasem mnożenie, a więc ostateczny wynik 68. 4. L wartość. L wartością (ang. L value) nazywamy to, co może stać po lewej stronie operatora przypisania (czyli po lewej stronie znaku=). double,*a; a=&; =55; lub *a=55. Instrukcja (*a=55;) nakazuje policzyć wartość wyrażenia znajdującego się po prawej stronie znaku równości i zapisać ją do kolejnych 8 bajtów, z których pierwszy ma adres zapisany w a. Wyrażeniem wskaźnik możemy posługiwać się w takich samych sytuacjach jak zmienną. 5. Zastosowanie wskaźników. Wskaźniki najczęściej stosuje się w sytuacjach, gdy chodzi nam o: - funkcje mogące zmieniać wartość przesyłanych do nich argumentów, - ulepszenie pracy z tablicami, - rezerwację obszarów pamięci. 6. Przykłady zastosowania wskaźników w funkcjach. Zadanie. Dane jest r promień koła. Obliczyć pole i obwód koła o zadanym promieniu r. o= r p= r Założenia: Pole i obwód mają być obliczane w funkcji o nazwie kolo, wartości pola i obwodu winny być znane w funkcji wywołującej. Rozwiązanie:
Treść programu objaśnienia #define PI 3.141596535897933846 Polecenie preprocesora używane często do nadawania nazw stałym. Identyfikator PI możemy używać wszędzie tam, gdzie powinna wystąpić liczba. #include<stdio.h> #include<math.h> void main() Typ void oznacza funkcję, która nie zwraca żadnej wartości. { double r,p,o,*oo; Definicja zmiennych jest żądaniem przydzielenia miejsca w pamięci. Po definicji znane są adresy zmiennych, ale nie są znane ich wartości. double kolo(); Prototyp funkcji. printf( podaj promień: ); scanf( %lf,&r); p=kolo(r,&o); Aktualne argumenty funkcji kolo. Do funkcji przekazywana jest wartość r oraz adres o. printf( %lf %lf %lf\n,r,o,p); } double kolo(double r, double *w) Deklaracja parametrów formalnych funkcji- r zmienna typu double, w wskaźnik do typu double. { double pom; Wartość pom, która będzie zwracana instrukcją return pom=pi*r*r; *w=*pi*r; W miejsce wskazywane przez w wstawić obwód koła. return pom; }
W funkcji main można dołączyć wydruk: printf( &r=%u &o=%u &p=%u &oo=%u\n,&r,&o,&p,&oo); printf( r=%lf\n,r); a w funkcji kolo można dołączyć: printf( &r=%u &w=%u &pom=%u\n,&r,&w,&pom); printf( r=%lf w=%u pom=%lf\n,r,w,pom); A oto jak graficznie prezentują się zmienne w funkcji main: double r,p o *oo; - rezerwacja pamięci dla zmiennych r, p, o, oo Nazwa Adres Zawartość r 314768 o 31475 p 314760 oo 314748 scanf( %lf,&r); - nadanie wartości r Nazwa Adres Zawartość r 314768 np.1.0 o 31475 p 314760 oo 314748 p = kolo(r,&o); - wywołanie funkcji kolo z wartościami: 1.0 oraz 31475 double kolo(double r, double *w) Nazwa Adres w funkcji kolo Zawartość r 314736 1.0 w 314744 31475
double pom; - definicja wewnętrznej pom Nazwa Adres w funkcji kolo Zawartość pom 31470 pom=pi*r*r; -nadanie wartości pom *w=*pi*r; -nadanie wartości o z funkcji main dzięki znajomości adresu o poprzez zmienną w powrót do funkcji main: Nazwa Adres Zawartość r 314768 1.0 o 31475 6.83185 p 314760 3.141593 oo 314748 Warto zwrócić uwagę, że możemy inaczej wywołać funkcję kolo: oo=&o; p=kolo(r,oo); Wówczas zawartość oo będzie adresem o, czyli liczbą 31475. 7. Zadania do samodzielnego wykonania z użyciem wskaźników. 7.1. Dane jest a,b,c długości boków trójkąta. Obliczyć pole trójkąta i promień koła wpisanego w trójkąt. Wykorzystać wzory Herona: pole : promień : S p( p a)( p b)( p c) S, gdzie p to pół długości obwodu trójkąta. p 7.. Dane są dwie liczby typu int a i b. Obliczyć iloraz a przez b oraz resztę z dzielenia. 7.3. Dane jest : r promień podstawy walca, h wysokość walca. Obliczyć objętość walca i pole powierzchni walca.
7.4. Dane są trzy liczby: a,b,c. Obliczyć największą z tej trójki liczb i podać numer pozycji, na której wystąpiła, przypisując a (nr=1), b (nr=) i c(nr=3). 7.5. Dane są dwie liczby: i y. Zamienić miejscami wartości tych liczb. =3, y=5; po operacji: =5, y=3. 7.6. Napisać funkcję, która liczy i zwraca dwa wyniki dla zadanego : oraz 3. 7.7. Zdyskretyzować (stablicować) funkcję określoną kilkoma wzorami: drukując zarówno wartość funkcji jak i numer wzoru wg którego wartość z została policzona. (1) z () (3) y 1 y dla dla y dla y y 5 y 1 1 i y 5 7.8. Obliczyć sumę i ilość liczb wczytywanych do momentu kiedy wczytana liczba równa jest zero. 7.9. Dany jest ciąg liczb typu int różnych od zera. Ostatnia jest równa zero. Dane są również dwie liczby: a, b typu int. Obliczyć ile w tym ciągu jest liczb mniejszych od a, ile zawartych w przedziale [a,b], ile większych od b. 7.10. Dany jest ciąg współrzędnych punktów: 1,,..., n,0 oraz y 1,y,...,y n,0. Cyfra 0 kończy wymienione ciągi i nie jest brana pod uwagę jako współrzędna. Podać ile punktów znajduje się w poszczególnych ćwiartkach układu współrzędnych. 7.11. Dla zadanego i obliczyć sumę: e 1 1!! 3 3! aż do momentu, gdy i i! oraz liczbę wyrazów, która została wzięta do obliczenia sumy. 7.1. Napisać funkcję, która znajduje pierwiastek równania nieliniowego:
sin 0.5 = 0 w zadanym przedziale [a,b] z zadaną dokładnością metodą bisekcji oraz dodatkowo zwraca informację: 1 gdy pierwiastek znaleziono z zadaną dokładnością, 0 gdy pierwiastka nie znaleziono.