Wskaźniki

30
Wskaźniki Wskaźniki

description

Wskaźniki. Definiowanie wskaźników. Wskaźnik może wskazywać na obiekt dowolnego typu. Przykłady:. int * w; char * Wsk_Znak; float * Wskaz_Real;. Wskaźnik przechowuje adres obiektu wskazanego typu. - PowerPoint PPT Presentation

Transcript of Wskaźniki

Page 1: Wskaźniki

WskaźnikiWskaźniki

Page 2: Wskaźniki

Definiowanie wskaźników

Wskaźnik może wskazywać na obiekt dowolnego typu.

int * w; char * Wsk_Znak; float * Wskaz_Real;

Przykłady:

Wskaźnik przechowuje adres obiektu wskazanego typu.

Wskaźnik służący do pokazywania obiektów jednego typu nie nadaje się do pokazywania obiektów innego typu.

Page 3: Wskaźniki

Praca ze wskaźnikiem

Do nadania wskaźnikowi wartości początkowej służy jednoargumentowy operator &.

Oblicza on adres obiektu, który stoi po prawej stronie operatora przypisania.

Przykład:

int * w; // definicja wskaźnika do obiektów //typu int

int k = 10; // definicja i inicjalizacja zwykłego //obiektu typu int

w = &k; // ustawienie wskaźnika na obiekt k cout << * w; // wypisanie zawartości obiektu * w

Page 4: Wskaźniki

Praca ze wskaźnikiem

#include <iostream.h>#include <conio.h>void main (){ int zmienna = 8, druga = 4; int *wskaznik; clrscr (); wskaznik = &zmienna; // ustawienie

// wskaźnika na zmienna cout << "zmienna = " << zmienna

<< "\n a odczytana przez wskaźnik = " << * wskaznik << endl;

cdn.

Page 5: Wskaźniki

zmienna = 10; cout << "zmienna = " << zmienna

<< "\n a odczytana przez wskaźnik = " << * wskaznik << endl;

* wskaznik = 200; cout << "zmienna = " << zmienna

<< "\n a odczytana przez wskaźnik = " << * wskaznik << endl;

wskaznik = &druga; cout << "zmienna = " << zmienna

<< "\n a odczytana przez wskaźnik = " << * wskaznik << endl;

}

Page 6: Wskaźniki

Uwagi:

Do danego obiektu można odnosić się na dwa sposoby:

Operacja odniesienia się * do danego obiektu może być zarówno po prawej, jak i po lewej stronie operatora przypisania, np.:

przez jego nazwę przez zorganizowanie wskaźnika, który będzie na ten

obiekt pokazywał.

a = * Wskaznik;* Wskaznik = 100 + a;

Page 7: Wskaźniki

Wskaźnik typu void:

Wskaźnik jest to adres miejsca w pamięci plus informacja o tym, jakiego typu obiekt się pokazuje.

Można jednak zdefiniować wskaźnik bez tej wiedzy:

void * Wsk;

gdzie * Wsk jest wskaźnikiem dowolnego typu void.

Page 8: Wskaźniki

Przykład:

int * wi1, * wi2;float * wf;

wi1 = wi2; wf = wi1; // błąd

wf = ( float *) wi1;

void * wv;char * wch;int * wi;float * wf;

wv = wf; wv = wch; wv = wi;

Page 9: Wskaźniki

Uwagi:

Wskaźnik każdego niestałego typu można przypisać wskaźnikowi typu void;

Wskaźnika typu void nie można przypisać wskaźnikowi “prawdziwemu”.

Trzeba w takich przypadkach posłużyć się operatorem rzutowania:

wf = (float *) wv;wi = (int *) wv;wch = (char *) wv;

Page 10: Wskaźniki

Podstawowe zastosowanie wskaźników:

wskaźniki do tablic umożliwiające ulepszenie pracy z tablicami;

funkcje zmieniające wartości przesyłanych do nich argumentów;

rezerwacja obszarów pamięci.

Page 11: Wskaźniki

Wskaźniki do tablic

Nazwa tablicy jest równoważna (prawie...) wskaźnikowi do jej pierwszego elementu

const int MAX = 20;int *Wsk;// definicja wskaźnika na obiekty typu int

int Tab[MAX];

Wsk = Tab;lub

Wsk = &Tab[0];

Page 12: Wskaźniki

Wskaźniki do tablic

int *Wsk; // definicja wskaźnika na obiekty typu int

int Tab[20]; // definicja tablicy typu int

Wsk = &Tab [i]; // ustawienie wskaźnika na i-ty element //tablicy Tab

Wsk = &Tab [0];// inaczej:

Wsk = Tab;

Wsk = Wsk + 1; // inaczej: Wsk ++;

Wsk += n; // inaczej: Wsk = Wsk + n;

Page 13: Wskaźniki

Dwie poniższe instrukcje są równoważne:

Wsk = &Tab[0];Wsk = Tab;

Dwa poniższe zapisy są także równoważne:

Tab + 4 &Tab [4];

Jeśli Wsk = Tab, to:

Wsk++;Tab++; // BŁĄD

Nazwa tablicy jest stałym wskaźnikiem do niej samej!

Tab[5] *(Tab + 5) //zapisy równoważne

Page 14: Wskaźniki

Wskaźniki tablic można od siebie odejmować. Odjęcie od siebie dwóch wskaźników pokazujących

na różne elementy tej samej tablicy daje w wyniku liczbę dzielących je elementów tablicy.

Liczba ta może być dodatnia lub ujemna.

Wskaźniki można też ze sobą porównywać za pomocą operatorów relacji.

Page 15: Wskaźniki

Przesyłanie tablic do funkcji:

Do funkcji przesyłamy adres tablicy, np.:

void fun ( int tab [ ] );

Odbieramy tablicę z funkcji na dwa sposoby:

jako tablicę jako wskaźnik

Page 16: Wskaźniki

Wskaźnik do obiektu const

Jeśli funkcja otrzymuje adres tablicy, to pracuje w tym przypadku na oryginale tablicy i może dowolnie zmieniać wartości jej elementów.

Jeśli nie chcemy, aby funkcja te wartości zmieniała, to należy posłużyć się wskaźnikiem do stałego obiektu.

Taki wskaźnik wskazuje na obiekty, ale nie pozwala na ich modyfikację.

Page 17: Wskaźniki

Stałe wskaźniki:

Dotychczas mówiliśmy o wskaźnikach do obiektów stałych.

Są to wskaźniki, które nie mogą zmieniać pokazywanego obiektu. Traktują go jako obiekt stały.

Sam obiekt, na który pokazują nie musi być rzeczywiście stały.

Ważne jest to, że wskaźnik tak go traktuje.

Są jeszcze inne wskaźniki z przydomkiem const, które nazywamy wskaźnikami stałymi.

int Dworzec;int * const Wsk = & Dworzec;

Page 18: Wskaźniki

Stałe wskaźniki, a wskaźniki do stałych:

Stały wskaźnik to taki, który zawsze pokazuje to samo. Nie można nim poruszać.

Wskaźnik do stałego obiektu, to taki wskaźnik, który uznaje pokazywany obiekt za stały. Nie można go więc modyfikować.

Te dwa typy wskaźników można ze sobą łączyć, np.

const float * const Wsk = &a;

Page 19: Wskaźniki

Wskaźnik zawsze na coś pokazuje:

Jeden z najczęściej popełnianych błędów w programach ze wskaźnikami jest brak początkowego ustawienia wskaźnika.

Przy braku ustawienia następuje odczyt z przypadkowego miejsca w pamięci oraz zapis do przypadkowego miejsca.

void fun (){ float a; float * x, * m: // definicja wskaźników bez inicjalizacji

m = &a; // ustawienie wskaźnika m *x = 20.5; // wskaźnik x nie jest ustawiony!

// w tym momencie możemy skasować // potrzebną daną

}

Page 20: Wskaźniki

Rezerwacja obszarów pamięci:

Rezerwowanie i zwalnianie obszarów pamięci jest wykonywane za pomocą operatorów new i delete.

Operator new zajmuje się kreacją, a delete unicestwianiem obiektów.

Przykłady:

char * Wsk;

Wsk = new char; // utworzenie nowego obiektu t. char

delete Wsk; // zlikwidowanie tego obiektu

float * w;w = new float [10];delete [ ] w;

int * Wsk; Wsk = new int ( 50 );

Page 21: Wskaźniki

Cechy obiektów stworzonych operatorem new:

Obiekty takie istnieją od momentu, gdy je stworzyliśmy operatorem new do momentu, gdy je skasujemy operatorem delete. Więc, programista decyduje o czasie ich życia.

Obiekt tak utworzony nie ma nazwy. Można nim operować tylko za pomocą wskaźników.

Obiektów tych nie obowiązują zwykłe zasady o zakresie ważności. Jeśli tylko w danej chwili jest dostępny choćby jeden wskaźnik, który na taki obiekt wskazuje, to mamy dostęp do tego obiektu.

Tylko statyczne obiekty są inicjalizowane wstępnie zerami. Natomiast obiekty utworzone operatorem new po utworzeniu przechowują wartości przypadkowe.

Page 22: Wskaźniki

Dynamiczna alokacja tablicy:

int * Wsk_Tab; Wsk_Tab = new int [ Rozmiar ];

Rozmiar jest wyrażeniem typu int. Została stworzona nienazwana tablica

elementów typu int. Wynikiem działania operatora new jest

wskaźnik do początku tej tablicy.

Operator new daje swobodę. Tablica definiowana jest dynamicznie, w

trakcie wykonywania programu, np.:

Page 23: Wskaźniki

cout << Ile elementów ma mieć tablica?: ;int Rozmiar;cin >> Rozmiar;int * Wsk_Tab = new int [ Rozmiar ];

* Wsk_Tab = 50; // wpisanie do zerowego elementu// liczby 50

Wsk_Tab [0] = 50; // to samo inaczej

* (Wsk_Tab + 4) = 100; // wpisanie do elementu o indeksie 4// wartości 100

Wsk_Tab [4] = 100; // to samo inaczej

delete [ ] Wsk_Tab; // zlikwidowanie wykreowanej// tablicy

Page 24: Wskaźniki

Sposoby ustawienia wskaźników:

Wskaźnik można ustawić tak, aby pokazywał na jakiś obiekt, wstawiając do niego adres wybranego obiektu:

Wsk = & Obiekt;

Wskaźnik można również ustawić na to samo, na co pokazuje już inny wskaźnik. Jest to zwykła operacja przypisania wskaźników:

Wsk = Nowy_Wsk;

cdn.

Page 25: Wskaźniki

Wskaźnik ustawia się na początek tablicy podstawiając do niego jej adres. W zapisie jest niepotrzebny operator &:

Wsk = Tablica Wskaźnik może także pokazywać na funkcję. Nazwa

funkcji jest także jej adresem, zatem i tu zbędny jest operator &:

Wsk = Funkcja; Operator new zwraca adres nowoutworzonego obiektu.

Taki adres wpisujemy do wskaźnika. Od tej pory wskaźnik pokazuje na ten nowy obiekt:

float * Wsk;Wsk = new float;

Jeśli wskaźnik ma pokazywać na ciąg znaków, można go ustawić w taki sposób:

Wsk = Programowanie komputerów ;

Page 26: Wskaźniki

Tablice wskaźników:

Elementami tablic mogą być wskaźniki, czyli adresy różnych miejsc w pamięci, np.:

float * Wsk_Flo [10];

lub

float * (Wsk_Flo [10]);

char * Wsk_Lan [ 3];

char * Wsk_Lan [3] = { Matematyka, Fizyka, Progr. Komputerów};

char * Wsk = { abcde };

Page 27: Wskaźniki

Przykład 1:

Obliczyć wartości dwóch następujących całek:

3

2

23 dxx

dxx1

0

2sin

wykorzystując metodę Simpsona.

Page 28: Wskaźniki

Przybliżony wzór na obliczenie całki ma następującą postać:

b

a

dxxfI )(

3/))(...)()((2))(...)()((4)()( 2421310 mmm xfxfxfxfxfxfxfxfhI

gdzie:

m

abh

- długość podprzedziału

m - jest parzystą liczbą podprzedziałów.

Page 29: Wskaźniki

f(x) = 3*x*x

0

5

10

15

20

25

30

-2

-1,5 -1

-0,5 0

0,5 1

1,5 2

2,5 3

x

y

Page 30: Wskaźniki

#include <conio.h>#include <iostream.h>void main (){ int a = 1; int *Adr; int &r_a = a; Adr = &a; clrscr(); cout << *Adr << endl; cout << &r_a << endl; cout << &a << endl; cout << Adr << endl; cout << a << endl; cout << r_a << endl; r_a = 2; Adr = &r_a;

cout << Adr << endl; cout << *Adr << endl;}

Wskaźnik a referencja

1

0x8fa0fff4

0x8fa0fff4

0x8fa0fff4

1

1

0x8fa0fff4

2