Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

9 Adresy, wskaźniki ...............................................................................................................2

8.1

Przykłady operacji na tablicach ...............................................................................7

8.1.1

Tablica statyczna .............................................................................................7

8.1.2

Tablica dynamiczna – dostęp przez indeks ......................................................8

8.1.3

Tablica dynamiczna – dostęp przez wskaźnik ..................................................9

1

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

9 Adresy, wskaźniki

• Trzy podstawowe właściwości danych, które musi śledzić komputer: o Gdzie jest przechowywana informacja?

o Jaka wartość jest tam przechowywana?

o Jakiego rodzaju jest ta informacja?

• & - operator pobierania adresu np

int i = 5;

&i – adres zmiennej i w pamięci

5

0x4563 – adres tej komórki

Przykład 1

// w7p1.cpp -- uzycie operatora & do okreslenia adresu

#include <iostream>

using namespace std;

int main()

{

int ciastka = 6;

double szklanki = 4.5;

cout << "wartosc zmiennej ciastka = " << ciastka; cout << ", a adres tej zmiennej = " << &ciastka << endl;

// UWAGA: w niektorych implementacjach konieczne moze sie okazac uzycie

// unsigned (&ciastka) oraz unsigned (&szklanki)

cout << "wartosc zmiennej szklanki = " << szklanki; cout << ", a adres tej zmiennej = " << &szklanki << endl; return 0;

}

• Wskaźnik – zmienna, która przechowuje adres wartości a nie samą wartość.

• Deklaracja wskaźnika:

<typ> *<nazwa zmiennej> ;

Przykłady:

int liczba;

int *adresLiczby; // na zmiennej adresLiczby adres komórki typu int; 2

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

char znak;

char *adresZnaku; // na zmiennej adresZnaku adres komórki typu char;

• Przypisanie adresu do wskaźnika

<wskaźnik> = &<zmienna>;

Przykłady:

adresLiczby = &liczba; // adresLiczby wskazuje na int; adresLiczby to wskaźnik do int; adresZnaku = &znak; // adresZnaku wskazuje na char; adresZnaku to wskaźnik do char;

• Pobranie wartości z komórki wskazywanej przez wskaźnik:

<zmienna> = *<wskaźnik>;

Przykłady (przy załoŜeniu, Ŝe wykonano deklaracje i przypisania powyŜej): JeŜeli

liczba = 4;

to

*adresLiczby teŜ jest 4;

JeŜeli

znak = ‘A’;

to

*adresZnaku teŜ jest ‘A’;

// w7p2.cpp -- nasza pierwsza zmienna wskaznikowa

#include <iostream>

using namespace std;

int main()

{

int updates = 6; // deklaracja zmiennej

int * p_updates; // deklaracja wskaznika na int

p_updates = &updates; // przypisanie wskaznikowi adresu int

// pokazanie wartosci na dwa sposoby

cout << "Wartosci: updates = " << updates; cout << ", *p_updates = " << *p_updates << endl;

// pokazanie adresu na dwa sposoby

cout << "Adresy: &updates = " << &updates; cout << ", p_updates = " << p_updates << endl;

// uzycie wskaznika do zmiany wartosci

*p_updates = *p_updates + 1;

cout << "Teraz updates = " << updates << endl; return 0;

}

3

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

• UWAGA!

Nie wolno:

long *Lliczba; // Wartość zmiennej Lliczba = ?

*Lliczba = 5555555;

Dlaczego?

• Zawsze trzeba zainicjować wskaźnik ustalonym i prawidłowym adresem, zanim zastosuje się do niego operator wyłuskiwania (*)

• Przydzielanie pamięci – operator new.

• Składnia

new <nazwa typu danych>

Wartość:

Adres pierwszej wolnej komórki wielkości odpowiedniej do przechowywania określonego typu danych czyli sizeof(<nazwa typu danych>

int *wsk = new int; //rezerwujemy jedną komórkę pamięci i jej adres staje się wartością wsk.

Rezerwowanie więcej niŜ 1 komórki:

int *tab = new int[5];

• Przykład

// w7p3.cpp -- uzycie operatora new

#include <iostream>

int main()

{

using namespace std;

int * pt = new int; // alokacja pamieci na wartosc int

*pt = 1001; // zapis tam wartosci

cout << "int: ";

cout << "wartosc = " << *pt << ": polozenie = " << pt << endl; double * pd = new double; // alokacja pamieci na wartosc double

*pd = 10000001.0; // zapis tam wartoœci

cout << "double: ";

cout << "wartosc = " << *pd << ": polozenie = " << pd << endl; cout << "wielkosc pt = " << sizeof(pt);

4

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

cout << ": wielkosc *pt = " << sizeof(*pt) << endl; cout << "wielkosc pd = " << sizeof pd;

cout << ": wielkosc *pd = " << sizeof(*pd) << endl; return 0;

}

5

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

• Zwalnianie pamięci – operator delete

Składnia

delete <wskaźnik>;

Przykład:

int *ptr = new int; //alokujemy pamięć

// wykorzystujemy zaalokowaną pamięć

delete ptr;

// zwalniamy niepotrzebną pamięć

• UWAGA: OPERATORA DELETE NALEśY UśYWAĆ TYLKO DO

ZWALNIANIA PAMIECI ZAALOKOWANEJ PRZEZ NEW!

• Arytmetyka wskaźników

o Dodawanie / odejmowanie liczby całkowitej – przesunięcie o wielkość typu

int *ptr = new int[3];

++ptr;

--ptr;

6

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

8.1 Przykłady operacji na tablicach

8.1.1 Tablica statyczna

// w7p4.cpp -- znajdowanie max w wektorze

// wersja z tablica statyczna, dostep przez indeks

#include <iostream>

using namespace std;

int maks (int tab[], int wlk){

int pom = tab[0];

for (int i =0; i<wlk; ++i)

if (tab[i]>pom)pom = tab[i];

return pom;

}

int czytaj (int tab[], int wlk){

for (int i = 0; i<wlk; ++i)

{

cout << "Podaj element " << i << ": "; cin >> tab[i];

}

return 0;

}

void wypisz (int tab[], int wlk){

for (int i = 0; i<wlk; ++i)

cout << "Element " << i << ": "<< tab[i]<<endl;

}

int main()

{

const int MAKSEL = 100; // maksymalna liczba elementów w tablicy; int Liczby[MAKSEL];

int lElem; // rzeczywista liczba elementów - do wczytania

cout << "Podaj liczbe elementow ";

cin >> lElem;

// sprawdzenie, czy wczytana liczba jest poprawna

if (lElem <= 0 ) {

cout << "Podales "<< lElem << "jako liczbe elementow tablicy!"; cout <<" To nie jest poprawna liczba elem!"<<endl; return 1;

7

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

}

// tu juz liczba elementow jest poprawna

//*** rezerwujemy miejsce

if (czytaj (Liczby, lElem)<0) // blad przy czytaniu

return 1;

wypisz(Liczby, lElem);

cout << "Maksymalny element tablicy to " << maks(Liczby, lElem)<< endl; return 0;

}

8.1.2 Tablica dynamiczna – dostęp przez indeks

// w7p4a.cpp -- znajdowanie max w wektorze

// wersja z tablica dynamiczna, dostep przez indeks

#include <iostream>

using namespace std;

int maks (int tab[], int wlk){

int pom = tab[0];

for (int i =0; i<wlk; ++i)

if (tab[i]>pom)pom = tab[i];

return pom;

}

int czytaj (int tab[], int wlk){

for (int i = 0; i<wlk; ++i)

{

cout << "Podaj element " << i << ": "; cin >> tab[i];

}

return 0;

}

void wypisz (int tab[], int wlk){

for (int i = 0; i<wlk; ++i)

cout << "Element " << i << ": "<< tab[i]<<endl;

}

int main()

{

// const int MAKSEL = 100; // maksymalna liczba elementów w tablicy; int *Liczby;

int lElem; // rzeczywista liczba elementów - do wczytania

8

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

cout << "Podaj liczbe elementow ";

cin >> lElem;

// sprawdzenie, czy wczytana liczba jest poprawna

if (lElem <= 0 ) {

cout << "Podales "<< lElem << "jako liczbe elementow tablicy!"; cout <<" To nie jest poprawna liczba elem!"<<endl; return 1;

}

// tu juz liczba elementow jest poprawna

//*** rezerwujemy miejsce

Liczby = new int[lElem];

if (czytaj (Liczby, lElem)<0) // blad przy czytaniu

return 1;

wypisz(Liczby, lElem);

cout << "Maksymalny element tablicy to " << maks(Liczby, lElem)<< endl; return 0;

}

8.1.3 Tablica dynamiczna – dostęp przez wskaźnik

// w7p4b.cpp -- znajdowanie max w wektorze

// wersja z tablica dynamiczna, dostep przez wskaznik

#include <iostream>

using namespace std;

int maks (int *tab, int wlk){

int pom = *tab;

int *wsk;

for (wsk = tab; wsk<tab+wlk; ++wsk)

if (*wsk>pom) pom = *wsk;

return pom;

}

int czytaj (int *tab, int wlk){

int i = 0;

int *wsk;

for (wsk = tab; wsk<tab+wlk; ++wsk)

{

cout << "Podaj element " << i++ << ": "; cin >> *wsk;

}

9

Podstawy programowania. Wykład 7 – adresy, wskaźniki Małgorzata Nalbach-Moszyńska

return 0;

}

void wypisz (int *tab, int wlk){

int i = 0;

int *wsk;

for (wsk = tab; wsk<tab+wlk; ++wsk)

cout << "Element " << i++ << ": "<< *wsk<<endl;

}

int main()

{

// const int MAKSEL = 100; // maksymalna liczba elementów w tablicy; int *Liczby;

int lElem; // rzeczywista liczba elementów - do wczytania

cout << "Podaj liczbe elementow ";

cin >> lElem;

// sprawdzenie, czy wczytana liczba jest poprawna

if (lElem <= 0 ) {

cout << "Podales "<< lElem << "jako liczbe elementow tablicy!"; cout <<" To nie jest poprawna liczba elem!"<<endl; return 1;

}

// tu juz liczba elementow jest poprawna

//*** rezerwujemy miejsce

Liczby = new int[lElem];

if (czytaj (Liczby, lElem)<0) // blad przy czytaniu

return 1;

wypisz(Liczby, lElem);

cout << "Maksymalny element tablicy to " << maks(Liczby, lElem)<< endl; return 0;

}

10