Podstawy programowania w języku C++

Podobne dokumenty
Podstawy programowania w języku C++

Programowanie w języku C++

Wprowadzenie do programowania w języku C

Podstawy programowania w języku C++

Języki programowania obiektowego Nieobiektowe elementy języka C++

Podstawy programowania w języku C++

Podstawy programowania w języku C i C++

DYNAMICZNE PRZYDZIELANIE PAMIECI

Podstawy programowania w języku C++

ZASADY PROGRAMOWANIA KOMPUTERÓW

Wskaźniki. Informatyka

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

Lab 9 Podstawy Programowania

Programowanie w języku C++

Wykład 1: Wskaźniki i zmienne dynamiczne

Podstawy programowania komputerów

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

Podstawy programowania

Wprowadzenie do programowanie obiektowego w języku C++

Podstawy programowania w języku C++

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

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

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

Wykład 4: Klasy i Metody

Podstawy programowania w języku C++

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

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

Techniki Programowania wskaźniki

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

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

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

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

Podstawy programowania w języku C++

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

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

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

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:

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

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Wstęp do programowania

Wprowadzenie do programowania w języku C

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Język C zajęcia nr 11. Funkcje

Wstęp do programowania

Podstawy programowania w języku C++

Referencje do zmiennych i obiektów

Języki programowania obiektowego Nieobiektowe elementy języka C++

Podstawy programowania w języku C++

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Szablony klas, zastosowanie szablonów w programach

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

Wykład 8: klasy cz. 4

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

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 8. Karol Tarnowski A-1 p.

TEMAT : KLASY DZIEDZICZENIE

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Języki programowania obiektowego Nieobiektowe elementy języka C++

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

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

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

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

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

Zmienne, stałe i operatory

Zmienne i struktury dynamiczne

PARADYGMATY PROGRAMOWANIA Wykład 4

Język C++ Różnice między C a C++

Wyjątki (exceptions)

Wskaźniki w C. Anna Gogolińska

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

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

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

Język C++ zajęcia nr 2

Podstawy programowania. Wykład: 12. Struktury, unie, pola bitowe. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

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

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

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

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

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

Programowanie obiektowe

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

Programowanie i struktury danych. Wykład 4 Dr Piotr Cybula

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

Wykład 3 Składnia języka C# (cz. 2)

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

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

IX. Wskaźniki.(3 godz.)

Szablony funkcji i szablony klas

Podstawy programowania

Analiza konstrukcji zawierających wskaźniki. Piotr Błaszyński

Wskaźniki. Programowanie Proceduralne 1

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

Tbli Tablice obiektów biktó są tworzone dokładnie d tak samo, jak i tablice, składające się z elementów innego typu

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Transkrypt:

Podstawy programowania w języku C++ Część ósma Zmienne wskaźnikowe koncepcja, podstawowe zastosowania Wersja skrócona, tylko C++ Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa. Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne. Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione.

Co to jest zmienna przypomnienie Zmienna jest obiektem w programie, rezydującym w pamięci operacyjnej, przeznaczonym do przechowywania wartości pewnego typu. Każda zmienna ma swoją nazwę, oraz typ wartości. Zmienne są przechowywane w pamięci operacyjnej, liczba zajętych bajtów zależy od typu zmiennej. Nazwa zmiennej identyfikuje zmienną w programie zwalniając programistę od zastanawiania się, pod jakim adresem w pamięci zmienna jest zlokalizowana. Adres w pamięci... Nazwa zmiennej int i; i = 10; 02c4a45fh 10 i Wartość zmiennej... Copyright Roman Simiński Strona : 2

Zmienne wskaźnikowe motywacja do nauki Dokładne opanowanie zasad posługiwania się wskaźnikami jest niezbędne do efektywnego i sprawnego programowania w C i C++. Tej umiejętności nie można pominąć, przeskoczyć lub zostawić na później. Nie oszukujmy się ten, kto nie opanuje zasad posługiwania się wskaźnikami nigdy nie będzie prawdziwym, profesjonalnym programistą, wykorzystującym język C lub C++. Koncepcja wskaźników oraz metody ich wykorzystania są proste. Wymagają one jednak uwagi, zrozumienia i myślenia. Copyright Roman Simiński Strona : 3

Po co są zmienne wskaźnikowe? Zmienna wskaźnikowa przeznaczona jest do lokalizowania (inaczej wskazywania) obiektów w pamięci operacyjnej. Jedyną rolą zmiennej wskaźnikowej jest umożliwienie odwoływania się do obiektów wskazywanych. Pamięć operacyjna Zmienna wskaźnikowa Obiekt wskazywany Copyright Roman Simiński Strona : 4

Po co są zmienne wskaźnikowe? Zmienna wskaźnikowa rezyduje w pamięci operacyjnej. Zmienna wskaźnikowa może lokalizować w pamięci operacyjnej inne zmienne, nienazwane bloki pamięci oraz bloki zawierające kod programu, np. funkcje. Sama zmienna wskaźnikowa może być również wskazywana przez inną zmienną wskaźnikową. Zmienna wskaźnikowa Pamięć operacyjna Obiekt wskazywany Zmienna wskaźnikowa Copyright Roman Simiński Strona : 5

Trzy stany zmiennej wskaźnikowej Zmienna wskaźnikowa wskazuje na konkretny obiekt w pamięci: Pamięć operacyjna Zmienna wskaźnikowa Obiekt wskazywany OK Zmienna wskaźnikowa nie wskazuje na żaden obiekt: Pamięć operacyjna Zmienna wskaźnikowa OK Zmienna wskaźnikowa wskazuje na nie wiadomo co: Pamięć operacyjna Zmienna wskaźnikowa? Kiepsko Copyright Roman Simiński Strona : 6

Co zawiera zmienna wskaźnikowa? Zwykle przyjmuje się, że zmienna wskaźnikowa zawiera w sobie adres obiektu wskazywanego. Jednak zmienna wskaźnikowa nie musi w sobie zawierać adresu bezpośredniego (fizycznego). Zawartość zmiennej wskaźnikowej może zawierać inną informację, pozwalającą na precyzyjne i jednoznaczne zidentyfikowanie położenia obiektu w pamięci. Pamięć operacyjna Zmienna wskaźnikowa 345fa012h Obiekt wskazywany Adres: 345fa012h Copyright Roman Simiński Strona : 7

Przykład implementacji zmiennej wskaźnikowej Intel 8086 Zmienna wskaźnikowa zawiera przesunięcie (ang. offset) obiektu względem początku segmentu gdy wskaźniki są krótkie (ang. near) odwołania wewnątrz segmentu. Przesunięcie Adres segmentu Segment 02c4a45fh +0 +1 +2 +3 +4 Obiekt Krótka zmienna wskaźnikowa 0003 Copyright Roman Simiński Strona : 8

Przykład implementacji zmiennej wskaźnikowej Intel 8086 Zmienna wskaźnikowa zawiera adres segmentu i przesunięcie obiektu gdy wskaźniki są długie (ang. far) odwołania międzysegmentowe. Przesunięcie Adres segmentu Segment 02c4a45fh +0 +1 +2 +3 +4 Obiekt Długa zmienna wskaźnikowa 02c4a45f:0003 Copyright Roman Simiński Strona : 9

Deklaracja zmiennej wskaźnikowej Deklarowana zmienna będzie wskaźnikiem, kompilator wie, ile dla niej zarezerwować pamięci. To oznacza, że deklarowana zmienna wskaźnikowa będzie przeznaczona do lokalizowania w pamięci obiektów typu int. int * pi ; Nazwa deklarowanej zmiennej wskaźnikowej zbudowana wg. zwykłych reguł, często zawiera p lub ptr od pointer. int i = 10; int * pi; int i = 10; int * pi = NULL; Nazwa zmiennej Nazwa zmiennej i 10 i 10 Wartość zmiennej Wartość zmiennej pi?? pi Copyright Roman Simiński Strona : 10

Rola wskaźnika pustego NULL Tak zdefiniowana zmienna wskaźnikowa: int * pi; pi?? ma wartość początkową zależną od kontekstu deklaracji. Jeżeli ta zmienna jest klasy auto, to jej wartość jest przypadkowa zmienna wskazuje zatem na bliżej nieznany obiekt w pamięci. W pliku nagłówkowym stddef.h zdefiniowana stałą NULL, reprezentującą wskaźnik pusty, niezależny od platformy i implementacji. Tak zdefiniowana zmienna: int * pi = NULL; pi jest wskaźnikiem pustym, a więc nie wskazuje żadnego obiektu w pamięci. Copyright Roman Simiński Strona : 11

Wartość NULL kontra 0 Stała NULL jest definiowana jako wartość 0 lub 0L. Można zatem zamiast wartością NULL, posługiwać się wartością 0. W języku C praktykuje się stosowanie wartości NULL a nie wartości 0. W języku C++ praktykuje się stosowanie wartości 0 zamiast NULL. Niezależnie od przyjętej wartości wskaźnika pustego, jawnie inicjowanie zmiennych wskaźnikowych oraz posługiwanie się wartością pustą dla wskaźników niezakotwiczonych jest dobrą praktyką programistyczną w języku C i C++. To, czy zmienna wskaźnikowa jest wskaźnikiem pustym można sprawdzić: if( pi!= NULL ) // Tu jakie ś operacje na obiekcie // wskazywanym przez pi if( pi == NULL ) // Nie odwołujemy si ę do obiektu // wskazywanego przez pi nie ma go! Copyright Roman Simiński Strona : 12

Przypisywanie wartości zmiennym wskaźnikowym int i = 10; int * pi = NULL; i 10 int i = 10; int * pi = NULL; pi = &i; i 10 pi pi Od momentu tego przypisania, pi wskazuje zmienną i, i, umożliwiając realizację dowolnych operacji na tej zmiennej. pi = & i ; Wyrażenie wskaźnikowe lokalizujące zmienną i w pamięci. Jednoargumentowy operator & buduje wyrażenie wskaźnikowe lokalizujące zmienną w pamięci operacyjnej. Argument musi być l-wartością, nie odnoszącą się do obiektu register ani pola bitowego. Copyright Roman Simiński Strona : 13

Odwoływanie sie do obiektu wskazywanego int i = 10; int * pi = NULL; pi = &i; *pi = 20; i 20 *pi == i pi * pi = 20 ; Ten zapis oznacza obiekt wskazywany przez pi. Zapis *pi może wystąpić wszędzie tam, gdzie może wystąpić i. Jednoargumentowy operator adresowania pośredniego *, daje w wyniku obiekt wskazywany przez argument pi. Dowolne wyrażenie typu zgodnego z typem obiektu wskazywanego. Copyright Roman Simiński Strona : 14

Odwoływanie sie do obiektu wskazywanego, uwagi Po przypisaniu: pi = &i; te fragmenty kodu są równoważne: cin >> *pi; if( *pi == 0 ) cout << "Bledna wartosc"; else y = *pi * x; cout << "Wynik: " << y; cin >> i; if( i == 0 ) cout << "Bledna wartosc"; else y = i * x; cout << "Wynik: " << y; Jeżeli wskaźnik pi wskazuje na zmienną i, to *pi może wystąpić wszędzie tam, gdzie może wystąpić i. Zmienna pi jest linkiem (odnośnikiem) do zmiennej i, a wyrażenie *pi jest aliasem (alternatywną nazwą) zmiennej i. Copyright Roman Simiński Strona : 15

Typowe zastosowania zmiennych wskaźnikowych Realizacja przekazywania parametrów przez zmienną. Wykorzystanie pamięci zarządzanej dynamicznie. Manipulowanie tablicami. Budowa rekurencyjnych struktur danych. Copyright Roman Simiński Strona : 16

Przypomnienie: przekazywanie parametrów przez wartość void inc( int i ) i = i + 1; Jaka jest wartość a po wywołaniu inc? int a = 5; inc( a ); cout << a; Przed wywołaniem inc( a ) Wywołanie inc( a ) Wykonanie inc( a ) Po wykonaniu inc( a ) a 5 a 5 a 5 a 5 i 5 i 6 5X i=i+1 Copyright Roman Simiński Strona : 17

Wskaźniki a przekazywanie parametrów void inc( int * i ) *i = *i + 1; Jaka jest wartość a po wywołaniu inc? int a = 5; inc( &a ); cout << a; Parametr formalny i jest wskaźnikiem. Parametr aktualny wywołania również. Przed wywołaniem inc( a ) Wywołanie inc( a ) a 5 a 5 Wykonanie *i == a inc( a ) *i == a a 6 5X Po wykonaniu inc( a ) a 56 i i *i=*i+1 Copyright Roman Simiński Strona : 18

Wskaźniki typu void * Typ void * oznacza wskazanie niezwiązane z żadnym typem. Wskaźnik takiego typu może wskazywać daną dowolnego typu. float f = 2.5; int i = 5; char c = 'A'; void * ptr; ptr = &f; ptr = &i; Wskaźnik ptr może pokazywać na obiekty różnych typów. ptr = &c; Copyright Roman Simiński Strona : 19

Wskaźniki typu void *, cd.... Aby odwołać się do obiektu wskazywanego, należy poinformować kompilator jaki jest jego typ, dokonując konwersji (tzw. rzutowania) typu wskaźnika. void * ptr; ptr = &f; cout << endl << *( ( float * ) ptr ); Rzutowanie wskaźnika ptr wskazanie na obiekt typu float. void * ptr; ptr = &f; cout << endl << * ( float * ) ptr; Copyright Roman Simiński Strona : 20

Wskaźniki typu void *, cd.... Wskaźnik void * można rzutować na różne typy: float f = 2.5; int i = 5; char c = 'A'; void * ptr; ptr = &f; cout << endl << *( ( float * )ptr ); ptr = &i; cout << endl << *( ( int * )ptr ); ptr = &c; cout << endl << *( ( char * )ptr ); Copyright Roman Simiński Strona : 21

Pojęcie sterty, sterta a stos Sterta (ang. heap) to wydzielony obszar pamięci wolnej: przeznaczony do przechowywania danych dynamicznych, kontrolowany ręcznie przez programistę, ograniczony pod względem rozmiaru, Sterta przydzielany pasującymi fragmentami. Stos (ang. stack) to wydzielony obszar pamięci roboczej: Dane przeznaczony do przechowywania danych automatycznych, nie jest bezpośrednio kontrolowany przez programistę, Stos ograniczony pod względem rozmiaru, przydzielany wg. zasady LIFO (ang. last in, first out). Copyright Roman Simiński Strona : 22

Dynamiczny przydział pamięci Dynamiczny przydział pamięci polega na zarezerwowaniu fragmentu pamięci w obszarze pamięci wolnej (sterty), dla obiektu pamięciowego zwanego dynamicznym. Typowy scenariusz wykorzystania dynamicznego przydziału pamięci: Określenie wielkości potrzebnego obszaru pamięci. Przydział pamięci i zapamiętanie wskazania tego obszaru w zmiennej wskaźnikowej. Sprawdzenie czy przydział pamięci się powiódł, jeżeli tak to: Wykorzystanie przydzielonego bloku pamięci. Zwolnienie przydzielonego bloku pamięci, gdy nie jest już potrzebny. Copyright Roman Simiński Strona : 23

Dynamiczny przydział pamięci w języku C++ W języku C++ można używać funkcji obsługi sterty pochodzących z języka C, jednak w tym języku wprowadzono specjalne operatory zarządzające pamięcią: new oraz delete. Ich wykorzystanie jest zalecane a w wielu przypadkach konieczne. Operatory są częścią języka i współpracują z mechanizmami kontroli typów. Zatem w języku C++ zarządzanie pamięcią dynamiczną realizować będzie: operator new przydział pamięci, operator delete zwolnienie pamięci. Copyright Roman Simiński Strona : 24

Dynamiczny przydział pamięci w języku C++, przykład sprzed lat Zasady przydziału pamięci w C++: int main() int * p = 0; p = new int; if( p!= 0 ) *p = 10; cout << ++(*p); delete p; p = 0; W C++ wykorzystuje się wartość 0 jako wskaźnik pusty. Można korzystać ze stałej NULL, ale to wymaga włączenia odpowiedniego pliku nagłówkowego (np. stdlib). Copyright Roman Simiński Strona : 25

Dynamiczny przydział pamięci w języku C++, przykład na czasie Aktualnie, aby new oddało wartość 0, należy użyć jego specjalnej wersji: int main() int * p = 0; Stare dzieje w C ++ int main() int * p = 0; Aktualnie w C ++ p = new int; p = new (nothrow) int; if( p!= 0 ) *p = 10; cout << ++(*p); delete p; p = 0; if( p!= 0 ) *p = 10; cout << ++(*p); delete p; p = 0; Jeżeli nie użyjemy operatora w wersji new (nothrow), wygenerowany zostanie wyjątek bad_alloc. Copyright Roman Simiński Strona : 26

Dynamiczny przydział pamięci w języku C++, wyjątki Z wyjątkami współpracują instrukcje try i catch: int main() try int * p = new int; Aktualnie w C ++ *p = 10; cout << ++(*p); delete p; p = 0; catch( bad_alloc ) // Zrob cos gdy brak pamieci Mechanizm obsługi wyjątków oraz zasady stosowania try-catch zostaną omówione osobno. Copyright Roman Simiński Strona : 27