Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Podobne dokumenty
> C++ dynamiczna alokacja/rezerwacja/przydział pamięci. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

KURS C/C++ WYKŁAD 6. Wskaźniki

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

Laboratorium nr 9. Temat: Wskaźniki, referencje, dynamiczny przydział pamięci, tablice dynamiczne. Zakres laboratorium:

Zmienne i struktury dynamiczne

ZASADY PROGRAMOWANIA KOMPUTERÓW

Lab 9 Podstawy Programowania

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

DYNAMICZNE PRZYDZIELANIE PAMIECI

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Wykład 1: Wskaźniki i zmienne dynamiczne

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

W dowolnym momencie można zmienić typ wskaźnika.

Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Wstęp do wskaźników w języku ANSI C

Techniki Programowania wskaźniki

Podstawy programowania w języku C++

Typy wyliczeniowe Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Podstawy programowania w języku C++

Programowanie w C++ Wykład 4. Katarzyna Grzelak. 19 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 37

Wykład nr 3. Temat: Wskaźniki i referencje. Edward Morgan Forster

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Struktury, unie, formatowanie, wskaźniki

Podstawy programowania w języku C++

C++ wprowadzanie zmiennych

Wskaźniki. Informatyka

typ y y p y z łoż o on o e n - tab a lice c e w iel e owym m ar a o r we, e stru r kt k ury

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Wskaźniki w C. Anna Gogolińska

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Podstawy programowania. Wykład: 8. Wskaźniki. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

//zmienne globalne int *pa, *pb; //wskaźniki globalne void main(void) { clrscr(); printf("\n podaj wartosc liczby a\n"); scanf("%d",&a); pa=&a;

tablica: dane_liczbowe

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 4. Karol Tarnowski A-1 p.

Programowanie w języku C++

Język C zajęcia nr 11. Funkcje

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

Proste programy w C++ zadania

Zadeklarowanie tablicy przypomina analogiczną operację dla zwykłych (skalarnych) zmiennych. Może zatem wyglądać na przykład tak:

Programowanie komputerowe. Zajęcia 4

6 Przygotował: mgr inż. Maciej Lasota

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Spis treści WSKAŹNIKI. DYNAMICZNY PRZYDZIAŁ PAMIĘCI W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

Instrukcje warunkowe i skoku. Spotkanie 2. Wyrażenia i operatory logiczne. Instrukcje warunkowe: if else, switch.

Programowanie 2 - Tablice i łańcuchy

Zaawansowane programowanie w języku C++ Zarządzanie pamięcią w C++

Wymiar musi być wyrażeniem stałym typu całkowitego, tzn. takim, które może obliczyć kompilator. Przykłady:

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Programowanie obiektowe W3

INFORMATYKA Z MERMIDONEM. Programowanie. Moduł 5 / Notatki

Wskaźniki. Programowanie Proceduralne 1

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Podstawy Programowania Obiektowego

Tablice, funkcje, wskaźniki - wprowadzenie

Część 4 życie programu

Techniki Programowania wskaźniki 2

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

IX. Wskaźniki.(3 godz.)

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Deklaracja struktury w C++

Spis treści WSKAŹNIKI. DYNAMICZNY PRZYDZIAŁ PAMIĘCI W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

Materiał. Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Funkcje Wskaźniki Referencje Tablice dynamiczne Typ string Przeładowania funkcji

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Spis treści JĘZYK C - WSKAŹNIKI, DYNAMICZNY PRZYDZIAŁ PAMIĘCI. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

dr inż. Paweł Myszkowski Wykład nr 8 ( )

MACIERZE. Sobiesiak Łukasz Wilczyńska Małgorzata

Stałe, tablice dynamiczne i wielowymiarowe

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

MATERIAŁY DO ZAJĘĆ II

Podstawy Programowania C++

Podstawy programowania w języku C++

Informatyka I: Instrukcja 4.2

Algorytmy i język C++

Funkcje. Spotkanie 5. Tworzenie i używanie funkcji. Przekazywanie argumentów do funkcji. Domyślne wartości argumentów

Stałe i zmienne znakowe. Stała znakowa: znak

Podstawy programowania. Wykład PASCAL. Zmienne wskaźnikowe i dynamiczne. dr Artur Bartoszewski - Podstawy prograowania, sem.

Podstawy programowania 1

Języki i metodyka programowania. Wskaźniki i tablice.

Inicjacja tablicy jednowymiarowej

Programowanie i struktury danych

Programowanie i struktury danych

XV. Wskaźniki Odczytywanie adresu pamięci istniejących zmiennych Wskaźniki pierwsze spojrzenie.

Podstawy programowania skrót z wykładów:

część 8 wskaźniki - podstawy Jarosław Gramacki Instytut Informatyki i Elektroniki Podstawowe pojęcia

Wstęp do Programowania, laboratorium 02

Podstawy i języki programowania

Transkrypt:

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4 Dr inż. Dariusz JĘDRZEJCZYK Wskaźniki Dynamiczna alokacja pamięci Przykłady 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 2 Wskaźnik to zmienna (zwana zmienną wskaźnikową), która zawiera adres pierwszej komórki pamięci, w której przechowywana jest inna zmienna. Jeśli zmienna zajmuje więcej niż jedną komórkę pamięci to wskaźnik wskazuje na pierwszą z tych komórek. Dla każdego wskaźnika określany jest jego typ. Wskaźnik typu int wskazuje na zmienną typu int. Dzięki temu, kompilator wie ile komórek w pamięci zajmuje zmienna rozpoczynająca się w komórce, na którą wskazuje wskaźnik. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 3 1

1. int abc; 2. int *p; 3. p = &abc; lub 1. int abc; 2. int *p = &abc; 0 1 2 3 4 5 6 7 8 9 A B 0x2 0x5 0x8 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 4 & (operator pobrania adresu)- zwraca adres (numer komórki pamięci) zmiennej, która jest jego argumentem. p = &x; Do zmiennej p przypisana zostaje liczba będąca adresem zmiennej x. * (operator wyłuskania) - pozwala na odwołanie się do zawartości komórki pamięci lub komórek pamięci rozpoczynających się od podanego jako argument adresu. *p += 7; Do zmiennej umieszczonej pod adresem p dodawane jest 7. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 5 1. int a = 1, b = 2; 2. int *wsk; 3. wsk = &a; 4. cout<< "zmienna a = "<< a<< "\twskaznik = "<< *wsk<< endl; 5. a = 10; 6. cout<< "zmienna a = "<< a<< "\twskaznik = "<< *wsk<< endl; 7. *wsk = 20; 8. cout<< "zmienna a = "<< a<< "\twskaznik = "<< *wsk<< endl; 9. wsk = &b; 10. cout<< "zmienna a = "<< a<< "\twskaznik = "<< *wsk<< endl; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 6 2

L-wartość - operacja odniesienia się do danego obiektu: obiekt może znajdować się po prawej stronie znaku operatora przypisania = a = *wsk; obiekt może znajdować się po lewej stronie znaku operatora przypisania = *wsk = 1; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 7 ustawienie wskaźnika na elemencie tablicy o dowolnym indeksie n: int *wsk; int tab[10]; wsk = &tab[n]; ustawienie wskaźnika na początku tablicy: wsk = &tab[0]; lub wsk = tab; nazwa tablicy jest równocześnie adresem jej zerowego elementu przesuwanie wskaźnika po elementach tablicy: wsk = wsk + 1; lub wsk++; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 8 int *wsk; int tab[] = {100,200,300}; wsk = tab[2]; lub wsk = *(tab + 2); // definicja wskaźnika // definicja tablicy // ustawienie wskaźnika // ustawienie wskaźnika Z definicji obie te metody są równoważne. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 9 3

Dodawanie W języku C++ do wskaźników można dodawać lub odejmować liczby całkowite. Istotne jest jednak, że dodanie do wskaźnika liczby 2 nie spowoduje przesunięcia się w pamięci komputera o dwa bajty. Tak naprawdę przesuniemy się o 2*rozmiar zmiennej. Jest to bardzo ważna informacja. 1. int *ptr; 2. int a[] = {1, 2, 3, 5, 7}; 3. ptr = &a[0]; Gdy wykonamy instrukcję: 1. ptr += 2; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 10 Odejmowanie Wskaźniki można również od siebie odejmować, czego wynikiem jest odległość dwóch wskazywanych wartości. Odległość zwracana jest jako liczba obiektów danego typu, a nie liczba bajtów. Np.: int a[] = {1, 2, 3, 5, 7}; int *ptr = &a[2]; int diff = ptr - a; /*diff ma wartość 2 (a nie 2*sizeof(int))*/ Wynikiem może być oczywiście liczba ujemna. Operacja jest przydatna do obliczania wielkości tablicy (długości łańcucha znaków) jeżeli mamy wskaźnik na jej pierwszy i ostatni element. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 11 short int tablica[4] = {1, 2, 3, 4}; cout<< tablica[0], tablica[1], tablica[2], tablica[3]; cout<< tablica,*(tablica+1), *(tablica+2), *(tablica+3); Wynikiem działania takiego kodu będzie: 1 2 3 4 1 2 3 4 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 12 4

cout<< *(tablica++),*(tablica++),*(tablica++),*tablica; Jaki jest wynik działania tej linijki kodu? short int tablica[4] = {1, 2, 3, 4}; short int *p = tablica; for(int i=0; i<=3; i++){ } cout<< *p<< endl; p++; Wynikiem działania tego programu będzie: 1 2 3 4 for(int i=0; i<=3; i++) { cout<< *(p+i)<< endl; } 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 13 Czasami zdarza się, że nie wiemy, na jaki typ wskazuje dany wskaźnik. W takich przypadkach stosujemy typ void*. Sam void nie znaczy nic, natomiast void* oznacza "wskaźnik na obiekt w pamięci niewiadomego typu". Taki wskaźnik możemy potem odnieść do konkretnego typu danych (w języku C++ wymagana jest do tego operacja rzutowania). void *wskaznik = NULL; /* lub = 0; */ Po co zatem przypisywać wskaźnikowi 0? Po to, aby uniknąć błędów! Większość (jeśli nie wszystkie) funkcji, które zwracają wskaźnik w przypadku błędu zwrócą właśnie NULL, czyli zero. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 14 Ważne jest, aby przy posługiwaniu się wskaźnikami nigdy nie próbować odwoływać się do komórki wskazywanej przez wskaźnik o wartości NULL lub niezainicjowany wskaźnik! int *wsk; cout<< "zawartosc komorki: ", *(wsk)<< endl; /* Błąd */ wsk = 0; /* 0 w kontekście wskaźników to NULL */ cout<< "zawartosc komorki: ", *(wsk)<< endl; /* Błąd */ Należy również uważać, aby nie odwoływać się do komórek poza przydzieloną pamięcią, np.: int tab[] = { 0, 1, 2 }; tab[3] = 3; /* Błąd */ 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 15 5

Należy pamiętać o tym, iż używając operatora sizeof, podając zmienną wskaźnikową - uzyskana wielkość będzie wielkością wskaźnika, a nie wielkością typu użytego podczas deklarowania naszego wskaźnika. Zamiast tego należy używać: sizeof(*wskaźnik). char *zmienna; int a = sizeof(zmienna);/*a wynosi 4 - sizeof(char*) */ a = sizeof(char*); /*robimy to samo, co wyżej */ a = sizeof (*zmienna); /*zmienna a ma teraz przypisany rozmiar pojedynczego znaku, tj. 1 */ a = sizeof(char); /* robimy to samo, co wyżej */ 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 16 Tak jak istnieją zwykłe stałe, tak samo można mieć stałe wskaźniki - jednak są ich dwa rodzaje. wskaźniki na stałą wartość - to wskaźnik, którym nie można zmienić wskazywanej wartości const int *a; /*lub*/ int const *a; stałe wskaźniki - to wskaźnik, którego nie można przestawić na inny adres: int * const b; stały wskaźnik, którym nie można zmienić wartości wskazywanej zmiennej: const int *const c; /*lub*/ int const *const c; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 17 int i=0; const int *a=&i; int * const b=&i; int const * const c=&i; *a = 1; /* kompilator zaprotestuje */ *b = 2; /* ok */ *c = 3; /* kompilator zaprotestuje */ a = b; /* ok */ b = a; /* kompilator zaprotestuje */ c = a; /* kompilator zaprotestuje */ 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 18 6

Normalnie zmienne programu przechowywane są na tzw. stosie (ang. stack) - powstają, gdy program wchodzi do bloku, w którym zmienne są zadeklarowane a zwalniane w momencie, kiedy program opuszcza ten blok. Dostępny jest jednak drugi rodzaj rezerwacji (czyli alokacji) pamięci. Jest to alokacja na stercie (ang. heap). Sterta to obszar pamięci wspólny dla całego programu, przechowywane są w nim zmienne, których czas życia nie jest związany z poszczególnymi blokami. Musimy sami rezerwować dla nich miejsce i to miejsce zwalniać, ale dzięki temu możemy to zrobić w dowolnym momencie działania programu. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 19 Należy pamiętać, że rezerwowanie i zwalnianie pamięci na stercie zajmuje więcej czasu niż analogiczne działania na stosie. zmienna zajmuje na stercie więcej miejsca niż na stosie - sterta utrzymuje specjalną strukturę, w której trzymane są wolne partie (może to być np. lista). Tak więc używajmy dynamicznej alokacji tam: gdzie jest potrzebna - dla danych, których rozmiaru nie jesteśmy w stanie przewidzieć na etapie kompilacji lub ich żywotność ma być niezwiązana z blokiem, w którym zostały zaalokowane. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 20 Tworzenie zmiennej: int* zm; zm = new int; /*lub*/ int* zm = new int; Tworzenie tablicy jednowymiarowej: int rozmiar; float* tab; tab = new float[rozmiar]; /*lub*/ float* tab = new float[rozmiar]; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 21 7

Tworzenie tablicy dwuwymiarowej: int liczbawierszy, liczbakolumn float** tab = new float* [liczbawierszy]; for(int i=0; i<liczbawierszy; i++) tab[i] = new float [liczbakolumn]; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 22 Kasowanie zmiennej: delete zm; zm = NULL; Kasowanie tablicy jednowymiarowej: delete [] tab; tab = NULL; Kasowanie tablicy dwuwymiarowej: for(int i=0; i<liczbawierszy; i++) delete[] tab[i]; delete[] tab; tab = NULL; if(zm){ delete zm; zm = NULL; } 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 23 wskaźnik 'p' wskazujący na zmienną całkowitą - int *p; wskaźnik 'pp' wskazujący na wskaźnik wskazujący na liczbę całkowitą typu int - int **pp; wskaźnik 'ppp' wskazujący na wskaźnik wskazujący na wskaźnik wskazujący na liczbę typu int - int ***ppp; wskaźnik 'pa' wskazujący na tablicę liczb całkowitych typu int - int (*pa)[]; tablica 'ap' wskaźników na liczby całkowite typu int - int *ap[]; wskaźnik 'ppa' na wskaźnik wskazujący na tablicę liczb całkowitych typu int - int (**ppa)[]; wskaźnik 'pap' wskazujący na tablicę wskaźników na typ int - int *(*pap)[]; 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 24 8

Jednym z najczęstszych błędów: próby wykonania operacji na wskaźniku NULL, odwołania się do obszaru pamięci po jego zwolnieniu. Po wykonaniu operatora delete nie można już wykonywać żadnych odwołań do zwolnionego obszaru. odwołania do adresów pamięci, które są poza obszarem przydzielonym operatorem new, brak sprawdzania, czy dany wskaźnik nie ma wartości NULL, wycieki pamięci, czyli niezwalnianie całej, przydzielonej uprzednio pamięci 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 25 Dziękuję za uwagę i zapraszam na 15 minut przerwy. W dalszej części ćwiczenia do samodzielnego wykonania. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 26 Zadanie 1 Napisz program, w którym użytkownik może zadecydować o wielkości tablicy dwuwymiarowej. Ponadto stworzoną tablicę należy: wypełnić wszystkie elementy tablicy dowolną liczbą całkowitą, podaną przez użytkownika wypisać elementy tablicy w formacie "tab[i][j] - ułożenie w wierszach i kolumnach wypisać i-ty i j-ty element tablicy zapisać do i-tego i j-tego elementu tablicy zadaną liczbę całkowitą dodać nowy wiersz w zadanym miejscu dodać nową kolumnę w zadanym miejscu zmienić rozmiary tablicy. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 27 9

Zadanie 2 Napisz program pozwalający na tworzenie kwadratowej tablicy dwuwymiarowej. Aplikacja powinna mieć możliwość: zerowania elementów tablicy uzupełniania wartością 1 wszystkich przekątnych tej macierzy. Aplikacja powinna posiadać menu pozwalające na wybór przekątnej do uzupełnienia. 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 28 Zadanie 3 Napisz program, obliczający sumę liczb parzystych i nieparzystych składających się na liczbę podana przez użytkownika. Program ma ponadto zawierać menu umożliwiające wielokrotne użycie programu. np.: użytkownik podaje liczbę 7 to wtedy: na liczbę 7 składają się następujące cyfry: 0,1,2,3,4,5,6,7 suma liczb parzystych wynosi: 0+2+4+6 = 12, suma liczb nieparzystych wynosi: 1+3+5+7 = 16. Elementy tablicy powinny zostać odczytane z tablic przechowującej odpowiednio liczby parzyste i nieparzyste. Aplikacja powinna mieć możliwość: wprowadzenia liczby całkowitej przechowywania kolejnych liczb parzystych i nieparzystych w dwóch tablicach dynamicznych wypisywania na ekran wyniku w postaci podanej powyżej (tekst pochylony). 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 29 10