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