Podstawy programowania w języku C i C++

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

Podstawy programowania w języku C++

Wprowadzenie do programowania w języku C

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

Programowanie w języku C++

Wstęp do programowania

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

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

Podstawy programowania

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

Wstęp do programowania. Wykład 1

Podstawy programowania w języku C++

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

Podstawy programowania w języku C++

Wstęp do programowania

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

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

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

Język ludzki kod maszynowy

Podstawy programowania w języku C++

Przesłanianie nazw, przestrzenie nazw

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

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

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

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

Podstawy programowania w języku C++

Programowanie - wykład 4

Podstawy programowania w języku C i C++

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Pytania sprawdzające wiedzę z programowania C++

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Ćwiczenia podstawowe, zestaw 5, część 1

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Część 4 życie programu

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Przekazywanie argumentów wskaźniki

1 Podstawy c++ w pigułce.

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Podział programu na moduły

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Wstęp do programowania

Wyjątki (exceptions)

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

Wprowadzenie do programowanie obiektowego w języku C++

Podstawy programowania

Grzegorz Cygan. Wstęp do programowania mikrosterowników w języku C

Programowanie strukturalne i obiektowe

Programowanie w języku C++

Wykład II Tablice (wstęp) Przykłady algorytmów Wstęp do języka C/C++

1 Podstawy c++ w pigułce.

I - Microsoft Visual Studio C++

Projektowanie klas c.d. Projektowanie klas przykład

Tablice, funkcje - wprowadzenie

Język C++ zajęcia nr 2

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podstawy programowania w języku C++

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Zmienne, stałe i operatory

#include <iostream> using namespace std; void ela(int); int main( ); { Funkcja 3. return 0; }

Programowanie w języku C++ Grażyna Koba

Co nie powinno być umieszczane w plikach nagłówkowych:

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

Podstawy programowania w języku C++

Język C - podstawowe informacje

Języki C i C++ Wykład: 2. Wstęp Instrukcje sterujące. dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD

Podstawy Programowania. Wykład 1

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

Podstawy programowania w języku C++

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

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

Wstęp do informatyki- wykład 9 Funkcje

Spis treści WSTĘP CZĘŚĆ I. PASCAL WPROWADZENIE DO PROGRAMOWANIA STRUKTURALNEGO. Rozdział 1. Wybór i instalacja kompilatora języka Pascal

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

Podstawy algorytmiki i programowania - wykład 4 C-struktury

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

Przeciążenie (przeładowanie nazw) funkcji

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Wstęp do informatyki- wykład 11 Funkcje

C-struktury wykład. Dorota Pylak

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

C++ - [1-3] Debugowanie w Qt Creator

Laboratorium 3: Preprocesor i funkcje ze zmienną liczbą argumentów. mgr inż. Arkadiusz Chrobot

Język C zajęcia nr 11. Funkcje

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Funkcja (podprogram) void

Podstawy programowania. Wykład 9 Preprocesor i modularna struktura programów. Krzysztof Banaś Podstawy programowania 1

Podstawy Informatyki. Kompilacja. Historia. Metalurgia, I rok. Kompilatory C++ Pierwszy program. Dyrektywy preprocesora. Darmowe:

Programowanie strukturalne i obiektowe : podręcznik do nauki zawodu technik informatyk / Adam Majczak. Gliwice, cop

Wykład 8: klasy cz. 4

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Podstawy Informatyki. Metalurgia, I rok. Wykład 6 Krótki kurs C++

Szablony funkcji i szablony klas

Programowanie Obiektowe i C++

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

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

Do czego służą klasy?

Transkrypt:

Podstawy programowania w języku C i C++ Część piąta Funkcje i struktura programu 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.

Pierwsza własna funkcja #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku, pole; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku; pole = oblicz_pole_kwadratu( dlugosc_boku ); cout << "Pole: " << pole; return EXIT_SUCCESS; Copyright Roman Simiński Strona : 2

Pierwsza własna funkcja jak to działa? #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku, pole; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: ";» cin >> dlugosc_boku; pole = oblicz_pole_kwadratu( dlugosc_boku ); cout << "Pole: " << pole; dlugosc_boku pole?? return EXIT_SUCCESS; Copyright Roman Simiński Strona : 3

Pierwsza własna funkcja przed wywołaniem #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku, pole; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku;» pole = oblicz_pole_kwadratu( dlugosc_boku ); cout << "Pole: " << pole; dlugosc_boku pole 25? return EXIT_SUCCESS; Copyright Roman Simiński Strona : 4

Pierwsza własna funkcja wywołanie funkcji, przekazanie parametrów #include <iostream> #include <cstdlib> using namespace std; double» double oblicz_pole_kwadratu( double double bok bok ) ) return bok * bok; int main() double dlugosc_boku, pole; 25 bok 25 cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; dlugosc_boku pole 25? cin >> dlugosc_boku; pole = oblicz_pole_kwadratu( dlugosc_boku ); cout << "Pole: " << pole; return EXIT_SUCCESS; Copyright Roman Simiński Strona : 5

Pierwsza własna funkcja wykonanie funkcji #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok )» return bok * bok; ; int main() double dlugosc_boku, pole; 625 bok dlugosc_boku 25 25 cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; pole? cin >> dlugosc_boku; pole = oblicz_pole_kwadratu( dlugosc_boku ); cout << "Pole: " << pole; return EXIT_SUCCESS; Copyright Roman Simiński Strona : 6

Pierwsza własna funkcja po powrocie funkcji #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku, pole; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku; pole = oblicz_pole_kwadratu( dlugosc_boku );» cout << "Pole: " << pole; dlugosc_boku pole 25 625 return EXIT_SUCCESS; Copyright Roman Simiński Strona : 7

Pierwsza własna funkcja drobna optymalizacja #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku; Zmienna pole jest niepotrzebna, rezultat funkcji może być przekazany do strumienia wyjściowego bezpośrednio. cout << "Pole: " << oblicz_pole_kwadratu( dlugosc_boku ); return EXIT_SUCCESS; Copyright Roman Simiński Strona : 8

Ogólna postać definicji funkcji typ_rezultatu nazwa_funkcji( lista_parametrów_formalnych ) ciało_funkcji Przykłady prostych funkcji o charakterze obliczeniowym: double oblicz_pole_kwadratu( double bok ) return bok * bok; double oblicz_obwod_kwadratu( double bok ) return 4 * bok; double oblicz_delte( double a, double b, double c ) return b * b 4 * a * c; Copyright Roman Simiński Strona : 9

A co z procedurami? W języku C/C++ nie występuje podział podprogramów na procedury i funkcje. Wszystkie podprogramy są funkcjami. Istnieje jednak możliwość wykorzystywania funkcji jak procedur, bądź deklarowania funkcji tak, by przypominały procedury. Słowo kluczowe void, będące nazwą typu, oznacza brak, nieobecność jakiejkolwiek wartości. Jeżeli typem rezultatu będzie typ określany słowem kluczowym void, to oznacza, iż funkcja nie udostępnia rezultatu staje się wtedy czymś podobnym do procedury z języka Pascal. Copyright Roman Simiński Strona : 10

Jeżeli rezultat funkcji nie jest ważny? Procedura... void wyswietl_info( void ) cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku; wyswietl_info(); Zadaniem funkcji jest wyprowadzenie tekstu komunikatów. Nie potrzebuje parametrów, nie oddaje rezultatu. cin >> dlugosc_boku; cout << "Pole: " << oblicz_pole_kwadratu( dlugosc_boku ); return EXIT_SUCCESS; Copyright Roman Simiński Strona : 11

Kilka słów na temat definiowania funkcji Jeżeli w miejscu listy parametrów formalnych występuje słowo kluczowe void, to oznacza, że funkcja nie posiada parametrów. Jeżeli funkcja posiada rezultat, w ciele funkcji powinna wystąpić instrukcja return, a po niej, wyrażenie o typie zgodnym z typem rezultatu funkcji. Na liście parametrów formalnych, dla każdego parametru określamy jego typ. Nawiasy po nazwie funkcji są konieczne, nawet gdy funkcja nie ma parametrów. Nawiasy występują zarówno przy definicji, deklaracji jak i przy wywołaniu funkcji. Copyright Roman Simiński Strona : 12

Kilka słów na temat definiowania funkcji Wersja naiwna funkcji obliczania średniego spalania: float oblicz_spalanie( float paliwo, float dystans ) return ( paliwo * 100 ) / dystans; Próba ratowania się przed dzieleniem przez zero: float oblicz_spalanie( float paliwo, float dystans ) if( dystans!= 0 ) return ( paliwo * 100 ) / dystans; A jaki będzie rezultat funkcji, gdy dystans będzie równy zero? Copyright Roman Simiński Strona : 13

Kilka słów na temat definiowania funkcji Specyfikacja funkcji: oblicz średnie spalanie, ignoruj ujemne wartości parametrów, gdy dystans jest zerowy, niech rezultat będzie równy -1, co jest sygnałem błędu. float oblicz_spalanie( float paliwo, float dystans ) if( dystans == 0 ) return 1; else return fabs( ( paliwo * 100 ) / dystans );... spalanie = oblicz_spalanie( 40.5, 0 ); if( spalanie == -1 ) cout << "Nie dokonam oblicze ń dla błędnych danych"; else cout << "Spalanie wynosi " << spalanie << " l na 100 km";... Copyright Roman Simiński Strona : 14

Definiowanie funkcji pułapka pierwsza, rezultat typu int W języku C/C++ wolno czasem opuścić słowo kluczowe int, wtedy zostanie ono przyjęte domyślnie. To, że tak robić można nie oznacza, że tak robić trzeba. Zapisy równoważne: int fun( void )... fun( void )... Copyright Roman Simiński Strona : 15

Definiowanie funkcji pułapka druga, puste nawiasy parametrów Puste nawiasy parametrów w języku C i C++ oznaczają co innego. W języku C++ puste nawiasy oznaczają brak parametrów: Zapisy równoważne w C++: int fun( void ) ciało funkcji int fun() ciało funkcji W języku C puste nawiasy oznaczają zmienną liczbę parametrów: Zapisy równoważne w C: int fun(... ) ciało funkcji int fun() ciało funkcji Trzy następujące po sobie kropki... oznaczają zmienną liczbę parametrów, jakie można przekazać funkcji. Copyright Roman Simiński Strona : 16

Definiowanie funkcji zmienna liczba parametrów Funkcja o zmiennej liczbie parametrów: int a = 1, b = 2, c = 3, d = 4, e = 5; cout << suma_int( 3, a, b, c ) << endl; cout << suma_int( 2, e, c ) << endl; cout << suma_int( 5, a, b, c, d, e ) << endl; Funkcja printf ma zmienną liczbę parametrów: printf( "Witaj w programie" ); printf( "Kwota podatku wynosi %g", podatek ); printf( "Podstawa opodatkowania: %g, podatek: %g", podstawa, podatek ); Copyright Roman Simiński Strona : 17

Definiowanie funkcji zmienna liczba parametrów Kompilator nie kontroluje poprawności wywołania funkcji w części określonej zmienną liczbą parametrów. int a = 1, b = 2, c = 3, d = 4, e = 5; cout << suma_int( 3, a, b ) << endl; cout << suma_int( 2, e, c, a ) << endl; cout << suma_int( 5, "Ala", 3.56 ) << endl; // Za mało parametrów // Za dużo parametrów // Totalny rozjazd printf( "Witaj w programie", podatek ); printf( "Kwota podatku wynosi %g" ); int podstawa; printf( "Podstawa: %g", podstawa ); // Za dużo parametrów // Za mało parametrów // Nie ten typ parametru Obsługa i kontrola poprawności wywołania funkcji ze zmienną liczbą parametrów spoczywa na programiście! Copyright Roman Simiński Strona : 18

Przekazywanie parametrów przez wartość (język C i C++) void inc( int i ) ++i;... Co wyprowadzi program? int a = 5; inc( a ); cout << a; Copyright Roman Simiński Strona : 19

Przekazywanie parametrów przez wartość (język C i C++) void inc( int i ) ++i;... Jaki jest stan pamięci przed wywołaniem? int a = 5; inc( a ); cout << a; Przed wywołaniem inc( a ) a 5 Copyright Roman Simiński Strona : 20

Przekazywanie parametrów przez wartość (język C i C++) void inc( int i ) ++i;... Co się dzieje w trakcie wywołania? int a = 5; inc( a ); cout << a; Przed wywołaniem inc( a ) Wywołanie inc( a ) a 5 a 5 i 5 Copyright Roman Simiński Strona : 21

Przekazywanie parametrów przez wartość (język C i C++) void inc( int i ) ++i;... Co się dzieje w trakcie wykonania? int a = 5; inc( a ); cout << a; Przed wywołaniem inc( a ) Wywołanie inc( a ) Wykonanie inc( a ) a 5 a 5 a 5 i 5 i 6 5X ++i Copyright Roman Simiński Strona : 22

Przekazywanie parametrów przez wartość (język C i C++) void inc( int i ) ++i;... Jaki jest stan pamięci po wywołaniu? 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 Copyright Roman Simiński Strona : 23

Przekazywanie parametrów przez wartość (język C i C++) Przy przekazywaniu parametrów przez wartość, wartość parametru aktualnego wywołania funkcji kopiowana jest do parametru formalnego funkcji. Od tego momentu parametr aktualny i formalny są od siebie niezależne. Żadna modyfikacja parametru formalnego funkcji nie przenosi się na parametr aktualny wywołania. Wnętrze funkcji nie jest w stanie zmodyfikować parametru formalnego funkcji. Copyright Roman Simiński Strona : 24

Przekazywanie parametrów przez referencję (C++) void inc( int & i ) ++i;... Co wyprowadzi program? int a = 5; inc( a ); cout << a; Parametr formalny i jest referencją do parametru aktualnego wywołania funkcji Copyright Roman Simiński Strona : 25

Przekazywanie parametrów przez referencję (C++) void inc( int & i ) ++i;... Jaki jest stan pamięci przed wywołaniem? int a = 5; inc( a ); cout << a; Parametr formalny i jest referencją do parametru aktualnego wywołania funkcji Przed wywołaniem inc( a ) a 5 Copyright Roman Simiński Strona : 26

Przekazywanie parametrów przez referencję (C++) void inc( int & i ) ++i;... Co się dzieje w trakcie wywołania? int a = 5; inc( a ); cout << a; Parametr formalny i jest referencją do parametru aktualnego wywołania funkcji Przed wywołaniem inc( a ) Wywołanie inc( a ) a 5 a 5 i Copyright Roman Simiński Strona : 27

Przekazywanie parametrów przez referencję (C++) void inc( int & i ) ++i;... Co się dzieje w trakcie wykonania? int a = 5; inc( a ); cout << a; Parametr formalny i jest referencją do parametru aktualnego wywołania funkcji Przed wywołaniem inc( a ) Wywołanie inc( a ) Wykonanie inc( a ) a 5 a 5 i a 6 5X i ++i Copyright Roman Simiński Strona : 28

Przekazywanie parametrów przez referencję (C++) void inc( int & i ) ++i;... Jaki jest stan pamięci po wywołaniu? int a = 5; inc( a ); cout << a; Parametr formalny i jest referencją do parametru aktualnego wywołania funkcji Przed wywołaniem inc( a ) Wywołanie inc( a ) Wykonanie inc( a ) Po wykonaniu inc( a ) a 5 a 5 i a 6 5X i a 56 ++i Copyright Roman Simiński Strona : 29

Wykorzystanie parametrów referencyjnych (C++) Przy przekazywaniu parametrów przez referencję, parametr aktualny wywołania funkcji nakłada się na parametr formalny funkcji. Od tego momentu parametr aktualny i formalny odnoszą się do tej samej lokalizacji (adresu) w pamięci operacyjnej. Każda modyfikacja parametru formalnego funkcji przenosi się na parametr aktualny wywołania. Wnętrze funkcji może zmodyfikować parametr formalny funkcji. Copyright Roman Simiński Strona : 30

Funkcja a przekazywanie parametrów przez referencję (C++) Wczytywanie liczby wykorzystanie funkcji double czytajdystans() double liczba; do cout << endl << "Podaj dystans: "; cin >> liczba; if( liczba <= 0 ) cout << "Dystans musi byc liczba dodatnia"; while( liczba <= 0 ); return liczba; double dystans; dystans = czytajdystans(); Copyright Roman Simiński Strona : 31

Funkcja a przekazywanie parametrów przez referencję (C++) Wczytywanie liczby wykorzystanie parametru referencyjnego double czytajdystans( double & liczba ) do cout << endl << "Podaj dystans: "; cin >> liczba; if( liczba <= 0 ) cout << "Dystans musi byc liczba dodatnia"; while( liczba <= 0 ); double dystans; czytajdystans( dystans ); Copyright Roman Simiński Strona : 32

Definicja funkcji po jej wywołaniu int main() double dlugosc_boku, pole;... pole = oblicz_pole_kwadratu( dlugosc_boku ); Wywołanie funkcji... double oblicz_pole_kwadratu( double bok ) return bok * bok; Czy kompilatorowi się to spodoba? Definicja funkcji Copyright Roman Simiński Strona : 33

Czy kompilatorowi się to spodoba? int main() double dlugosc_boku, pole;... pole = oblicz_pole_kwadratu( dlugosc_boku ); Wywołanie funkcji... double oblicz_pole_kwadratu( double bok ) return bok * bok; Definicja funkcji Tak, bez błędów i ostrzeżeń w starszych wersjach kompilatorów. Tak, bez błędów lecz z ostrzeżeniem w nowszych wersjach kompilatorów, oraz tych pracujących w trybie zgodności z normą ANSI. Nie, wystąpi błąd w kompilatorach pracujących w trybie C++. Copyright Roman Simiński Strona : 34

Skąd te rozbieżności? Definicja funkcji występuje po jej wywołaniu. Kompilator na etapie wywołania jej jeszcze nie zna. Czyni w stosunku do niej założenia że to funkcja, której rezultatem jest wartość int. To założenie może być słusznie albo nie. Aby kompilator mógł kontrolować poprawność wywołania funkcji, należy to wywołanie poprzedzić definicją lub deklaracją wywoływanej funkcji. Aby uniknąć niejednoznaczności, wprowadza się prototypy funkcji. Deklaracja przyjmuje postać prototypu funkcji. Copyright Roman Simiński Strona : 35

Prototypy funkcji Definicja funkcji: double oblicz_pole_kwadratu( double bok ) return bok * bok; Deklaracja prototyp funkcji: double oblicz_pole_kwadratu( double bok ); Ogólna postać definicji funkcji: typ_rezultatu nazwa_funkcji( lista_parametrów_formalnych ) ciało_funkcji Ogólna postać prototypu funkcji: typ_rezultatu nazwa_funkcji( lista_parametrów_formalnych ); Copyright Roman Simiński Strona : 36

Wykorzystanie prototypów funkcji zadeklaruj funkcję potem wołaj #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ); int main() double dlugosc_boku; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku; cout << "Pole: " << oblicz_pole_kwadratu( dlugosc_boku ); return EXIT_SUCCESS; double oblicz_pole_kwadratu( double bok ) return bok * bok; Copyright Roman Simiński Strona : 37

Można jednak po paskalowemu zdefiniuj funkcje potem wołaj #include <iostream> #include <cstdlib> using namespace std; double oblicz_pole_kwadratu( double bok ) return bok * bok; int main() double dlugosc_boku; cout << endl << "Obliczam pole kwadratu"; cout << endl << "Podaj dlugosc boku: "; cin >> dlugosc_boku; cout << "Pole: " << oblicz_pole_kwadratu( dlugosc_boku ); return EXIT_SUCCESS; Copyright Roman Simiński Strona : 38

Podsumowanie informacji o prototypach Starsze implementacje C dopuszczały wywoływanie funkcji wcześniej kompilatorowi nieznanych. W trakcie kompilowania wywołania nieznanej funkcji przez domniemanie przyjmowano, że jej rezultatem jest wartość int i nic nie wiadomo na temat jej parametrów. Nie pozwalało to kompilatorowi kontrolować poprawności wywołania funkcji. Aby kompilator mógł kontrolować poprawność wywołania funkcji, należy to wywołanie poprzedzić definicją lub deklaracją wywoływanej funkcji. Deklaracja przyjmuje postać prototypu funkcji. Deklaracja i definicja funkcji powinna być zgodna. Jeżeli w obrębie jednego pliku wystąpi niezgodność, kompilator zgłosi błąd kompilacji. Copyright Roman Simiński Strona : 39

Deklaracje zmiennych a struktura programu klasa pamięci auto void fun( float a ) int i = 0; char c = 'A'; float f; if( i == 0 ) float i = 100.0; int k;... Przesłanianie identyfikatorów w obrębie tego bloku instrukcji if nazwa i oznacza, lokalną w tym bloki, zmienną typu float. Zmienne klasy auto mogą być definiowane na początku każdego bloku w C89, w standardzie C99 i w języku C++ każdym miejscu dozwolonym syntaktyką języka. Zmienne klasy auto pojawiają się wraz z wejściem sterowania do bloku w którym są zadeklarowane i znikają wraz z wyjściem sterowania z tego bloku. Zmienne deklarowane wewnątrz bloku są automatycznymi, jeżeli nie podano klasy pamięci albo jawnie użyto specyfikatora auto. Copyright Roman Simiński Strona : 40

Deklaracje zmiennych a struktura programu klasa pamięci auto void fun( float a ) int i = 0; int j; cout << "a = " << a << " i = " << i << " j = " << j << endl; int main() fun( 1.0 ); fun( 2.0 ); fun( 3.0 ); return EXIT_SUCCESS; Zmienne klasy auto: Nie zachowują swoich wartości pomiędzy swoimi kolejnymi kreacjami. O ile nie zostaną zainicjalizowane, maja wartości przypadkowe. Parametry formalne funkcji też są klasy auto. Copyright Roman Simiński Strona : 41

Deklaracje zmiennych a struktura programu klasa pamięci auto Zmienna klasy auto tworzone są automatycznie i lokowane są na stosie. Stos to element procesu, służący do przechowywania danych chwilowych. Na stosie lokowane są zmienne auto, w tym argumenty funkcji, oraz adresy powrotu dla wywoływanych podprogramów. Stos ma ustalony i ograniczony rozmiar należy sprawdzić ustalenia rozmiaru stosu w opcjach kompilatora (lub konsolidatora). Może się zdarzyć, że stos ma rozmiar rzędu kilku kilobajtów. Wobec powyższego, niebezpieczna może być poniższa definicja dużej tablicy: void fun( void ) float tab[ 10000 ];... Copyright Roman Simiński Strona : 42

Deklaracje zmiennych automatycznych w obrębie instrukcji W C++ można definiować zmienne w obrębie ograniczonym zasięgiem instrukcji: for( int i = 10; i > 0; i--) cout << endl << i << "..."; i = 0; // Błędna odwołanie poza zasięgiem switch( char c = getchar() ) case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': cout << "Samogloska " << c; break;... c = getchar(); // Błędna odwołanie poza zasięgiem Copyright Roman Simiński Strona : 43

Deklaracje zmiennych a struktura programu klasa pamięci static void fun_auto() int i = 1; cout << endl << "Auto " << i++; void fun_static() static int i = 1; cout << endl << "Static " << i++; int main() fun_auto(); fun_static(); fun_auto(); fun_static(); fun_auto(); fun_static();... Copyright Roman Simiński Strona : 44

Deklaracje zmiennych a struktura programu klasa pamięci static Zmienne statyczne mogą być lokalne w bloku lub zewnętrzne dla wszystkich bloków. Jeżeli zmienna wewnątrz bloku zostanie zadeklarowana ze specyfikatorem static, to: jest raz inicjowana wartością inicjalizatora lub nadawana jest jej wartość zerowa odpowiednio do typu. przechowuje wartość po opuszczeniu i ponownym wejściu do bloku. Statyczne zmienne lokalne stanowią prywatną, nieulotną pamięć danej funkcji czy bloku. Copyright Roman Simiński Strona : 45

Deklaracje zmiennych a struktura programu klasa pamięci static Przykład wykorzystania zmiennej statycznej funkcja z limitem wywołań w obrębie pojedynczego wykonania programu: void funkcja_z_limitem_wywolan( void ) static int licznik_wywolan = 0; if( licznik_wywolan < 10 ) licznik_wywolan++; // Tutaj odpowiednie instrukcje else cout << "Wersja demo -- limit wywolan wyczerpany"; Copyright Roman Simiński Strona : 46

Deklaracje zmiennych a struktura programu klasa pamięci register Deklaracja zmiennej jako register jest równoważna z deklaracją auto, ale wskazuje że deklarowany obiekt będzie intensywnie wykorzystywany, i w miarę możliwości będzie umieszczony w rejestrze procesora. Jeżeli nie jest możliwe umieszczenie zmiennej w rejestrze, pozostaje ona w pamięci. Zmienne rejestrowe pozwalają zredukować zajętość pamięci i poprawić szybkość wykonania operacji takie zmienne wykorzystujących. Jednak większość współczesnych kompilatorów wykorzystuje optymalizację rejestrową, zatem wiele zmiennych i tak przechowywanych jest w rejestrach, mimo braku jawnej specyfikacji jako register. register int i; for( i = 0; i < 10; i++ )... int very_time_critical_fun( register int i )... Copyright Roman Simiński Strona : 47

Deklaracje zmiennych a struktura programu klasa pamięci extern double dystans, paliwo; void czytaj_dane()... cin >> dystans;... cin >> paliwo; void pisz_wyniki() if( dystans == 0 ) cout << "Nie policze spalania dla zerowego dystansu" ); else cout << "Spalanie " << ( paliwo * 100 ) / dystans << "l na 100 km" ; int main()... czytaj_dane(); pisz_wyniki(); return EXIT_SUCCESS; Copyright Roman Simiński Strona : 48

Deklaracje zmiennych a struktura programu klasa pamięci extern Zmienne zewnętrzne deklarowane są na zewnątrz wszystkich funkcji. Zasięg zmiennej zewnętrznej rozciąga się od miejsca deklaracji do końca pliku. Zmienne zewnętrzne istnieją stale, nie pojawiają się i nie znikają, zachowują swoje wartości i są dostępne dla wszystkich funkcji programy występujących w zakresie danej zmiennej. Zmienna zewnętrzna jest raz inicjowana wartością inicjalizatora lub nadawana jest jej wartość zerowa odpowiednio do typu. Jeżeli dla zmiennej zewnętrznej użyjemy specyfikacji static, to oznacza to uprywatnienie (ograniczenie dostępu) w obrębie danego pliku źródłowego. Zmienne zewnętrzne oraz ich właściwe definiowanie i deklarowanie mają istotne znaczenie przy organizacji programów wielomodułowych. Copyright Roman Simiński Strona : 49

Definicje zmiennych o ustalonej wartości Słowo kluczowe const oznacza modyfikator często używany w C++, dostępny jest również choć rzadziej używany w języku C. Modyfikator const użyty w definicji zmiennej lub parametru oznacza, że wartość takiego elementu nie może być zmieniana po zainicjowaniu. const int i = 1;... i = 5; // Niedozwolone Aby wnętrze funkcji nie mogło zmodyfikować parametru aktualnego: void print_int( const int & i ) cout << i; void inc( const int & i ) ++i; // Nie wolno! Mimo, że modyfikator const występuje w C i C++ występują pewne różnice w możliwości jego wykorzystania, co zostanie omówione później. Copyright Roman Simiński Strona : 50

Definicje zmiennych o nieprzewidywalnie zmiennej wartości Słowo kluczowe volatile to modyfikator oznaczający obiekt o wartościach zmieniających się w nieprzewidywalny sposób, inaczej obiekty ulotne. Obiektami takimi mogą być zmienne odnoszące się do obiektów zewnętrznych w stosunku do programu zmiennych nałożonych na porty We/Wy, odnoszących się do obszarów BIOS'a, systemu operacyjnego. Takie zmienne nie powinny być poddawane optymalizacjom szczególnie optymalizacji rejestrowej. Specyfikacja volatile zapobiega wszystkim potencjalnym optymalizacjom. volatile unsigned char kbdstate =... ; // Zmienna nałożona na dane BIOS while( kbdstate & LR_SHIFT ) if( kbdstate & L_SHIFT ) // co ś tam... if( kbdstate & R_SHIFT ) // co ś tam...... Ponieważ zmienna kbdstate jest z iteracji while często wykorzystywana, kompilator może przenieść ją do rejestru procesora. Sprawi to, że ten fragment programu nie będzie działał poprawnie. Copyright Roman Simiński Strona : 51

Funkcje w osobnym module Funkcje o podobnym przeznaczeniu mogą być grupowane w moduły. Języki C i C++ nie oferują zdefiniowanej syntaktycznie modularyzacji. Jednak program może się składać z kompilowanych oddzielnie części zwanych właśnie modułami łączonych potem przez konsolidator (wraz z bibliotekami) w plik wykonywalny. Przyjęta konwencja budowania modułów zakłada oddzielenie części publicznej (nagłówkowej) modułu od części implementacyjnej (realizacyjnej). Moduł Część nagłówkowa modułu Tutaj deklaracje elementów eksportowanych przez moduł to moduł udostępnia. Część implementacyjna modułu Tutaj kod oraz deklaracje składowych modułu, również prywatnych (wewnętrznych) Plik nagłówkowy, rozszerzenia:.h,.hpp,.hxx Plik realizacyjny, rozszerzenia:.c,.cpp,.cxx Copyright Roman Simiński Strona : 52

Część publiczna a cześć implementacyjna Część publiczna modułu zawiera opis elementów dostępnych do użytku w innych modułach programu. W językach C i C++ część publiczna modułu to osobny plik plik nagłówkowy (rozszerzenie h, hpp, hxx). Plik nagłówkowy jest plikiem tekstowym, udostępniany jest i dystrybuowany w wersji tekstu jawnego. Część implementacyjna modułu zawiera wszystko to, co potrzebne jest dla działania elementów udostępnianych przez moduł. W językach C i C++ część implementacyjna modułu to osobny plik zwykły plik programu (rozszerzenie c, cpp, cxx). Część implementacyjna może być udostępniana i dystrybuowana w postaci źródłowej lub skompilowanej (pliki o, obj, lib). Copyright Roman Simiński Strona : 53

Funkcje w osobnym module przykład Załóżmy, że chcemy stworzyć moduł o nawie fun, w którym będą zdefiniowane funkcje obliczające pola i obwody figur płaskich. Zaczniemy od modułu udostępniającego następujące funkcje: double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); Inne moduły programu będą mogły wykorzystywać funkcje zdefiniowane w module fun. Copyright Roman Simiński Strona : 54

Funkcje w osobnym module koncepcja Program główny: main.cpp int main()... cout << pole_kwadratu( 10 ) << endl; cout << obwod_kwadratu( 10 ) << endl; cout << pole_kola( 10 ) << endl; cout << obwod_kola( 10 ) << endl;... return EXIT_SUCCESS; Moduł z funkcjami: fun double pole_kwadratu( double bok ) return bok * bok; double obwod_kwadratu( double bok ) return 4 * bok; double pole_kola( double promien ) return 3.14 * promien * promien; double obwod_kola( double promien ) return 2 * 3.14 * promien; Wywołania funkcji udostępnianych przez moduł fun Definicje funkcji udostępnianych przez moduł fun Copyright Roman Simiński Strona : 55

Funkcje w osobnym module podział modułu na części Moduł z funkcjami: fun double pole_kwadratu( double bok ) return bok * bok; double obwod_kwadratu( double bok ) return 4 * bok; double pole_kola( double promien ) return M_PI * promien * promien; double obwod_kola( double promien ) return 2 * M_PI * promien; Definicje funkcji udostępnianych przez moduł fun Część publiczna modułu: fun.hpp double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); Część implementacyjna : fun.cpp double pole_kwadratu( double bok ) return bok * bok; double obwod_kwadratu( double bok ) return 4 * bok; double pole_kola( double promien ) return 3.14 * promien * promien; double obwod_kola( double promien ) return 2 * 3.14 * promien; Copyright Roman Simiński Strona : 56

Funkcje w osobnym module włączanie własnego pliku nagłówkowego Część implementacyjna : fun.cpp #include "fun.hpp" Moduły zwykle włączają własny plik nagłówkowy. W tym akurat przypadku nie jest to konieczne. double pole_kwadratu( double bok ) return bok * bok; double obwod_kwadratu( double bok ) return 4 * bok; Część publiczna modułu: fun.hpp double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); double pole_kola( double promien ) return 3.14 * promien * promien; double obwod_kola( double promien ) return 2 * 3.14 * promien; Copyright Roman Simiński Strona : 57

Funkcje w osobnym module włączanie innych plików nagłówkowych Część implementacyjna : fun.cpp #include "fun.hpp" #include <cmath> Włączenie pliku nagłówkowego zawierającego definicję stałej π : M_PI double pole_kwadratu( double bok ) return bok * bok; double obwod_kwadratu( double bok ) return 4 * bok; Część publiczna modułu: fun.hpp double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); double pole_kola( double promien ) return M_PI * promien * promien; double obwod_kola( double promien ) return 2 * M_PI * promien; Copyright Roman Simiński Strona : 58

Funkcje w osobnym module włączanie innych plików nagłówkowych Część publiczna modułu: fun.hpp #ifndef _fun_hpp_ #define _fun_hpp_ double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); #endif Próba włączenia pliku wiele razy: #include <iostream> #include <cstdlib> #include "fun.hpp"... #include "fun.hpp"... #include "fun.hpp" Dyrektywa umożliwiająca kompilację warunkową Prototypy funkcji zostaną włączone jeden raz Copyright Roman Simiński Strona : 59

Funkcje w osobnym module wykorzystanie pliku nagłówkowego Program główny: main.cpp #include <iostream> #include <cstdlib> int main()... cout << pole_kwadratu( 10 ) << endl; cout << obwod_kwadratu( 10 ) << endl; cout << pole_kola( 10 ) << endl; cout << obwod_kola( 10 ) << endl;... return EXIT_SUCCESS; Program główny: main.cpp #include <iostream> #include <cstdlib> #include "fun.hpp" int main()... cout << pole_kwadratu( 10 ) << endl; cout << obwod_kwadratu( 10 ) << endl; cout << pole_kola( 10 ) << endl; cout << obwod_kola( 10 ) << endl;... return EXIT_SUCCESS; Ostrzeżenie lub błąd kompilacji definicje (prototypy) tych funkcji nie są znane! Po włączeniu pliku nagłówkowego fun.hpp deklaracje tych funkcji są znane kompilatorowi Program w włączonym plikiem nagłówkowym skompiluje się poprawnie, ale nie powstanie wersja wykonywalna, ponieważ program jest jeszcze niekompletny.... Copyright Roman Simiński Strona : 60

Kompilator, konsolidator... przypomnienie Edytor Środowisko do tworzenia programu źródłowego Program źródłowy Plik (pliki) tekstowe, np.: - Pascal :.pas - C :.c - C++ :.cpp, cxx Błędy syntaktyczne (składniowe) Analizator s yntaktyczny Generator kodu mas zynowego Kod maszynowy przed konsolidacją Plik (pliki)object.: - Dos, Windows :.obj,.tpu - Unix :.o Błędy konsolidacji programu K o m p i l a t o r Kons olidator (ang. linker) Biblioteki standardowe, systemowe, specjalizowane Kod wykonywalny Plik wykonywalny : - Dos, Windows :.com,.exe - Unix :.out Błędy wykonania programu Środowisko uruchomieniowe (ang. debuger, profiler) Testowanie i uruchamianie Poprawki Modyfikacje Rozwój Wdrożenie programu Copyright Roman Simiński Strona : 61

Kompilacja + konsolidacja dla pojedynczego modułu main.cpp Wersja źródłowa iostream cstdlib fun.hpp Preprocesor main.cpp po preprocesingu Realizacja dyrektyw, w tym #include Plik tekstowy po rozwinięciu dyrektyw preprocesora Kompilator Kompilacja, generacja kodu maszynowego main.o Kod maszynowy, jeszcze nie gotowy do uruchomienia Pliki bibliotek Konsolidator Dołączenie kodu z bibliotek standardowych i innych zewnętrznych main.exe Program wykonywalny Copyright Roman Simiński Strona : 62

Kompilacja + konsolidacja dla programu wielomodułowego problem main.cpp Wersja źródłowa iostream cstdlib fun.hpp Preprocesor main.cpp po preprocesingu Realizacja dyrektyw, w tym #include Plik tekstowy po rozwinięciu dyrektyw preprocesora Kompilator Kompilacja, generacja kodu maszynowego Te etapy przebiegają podobnie do kompilacji programu jednomodułowego Pliki bibliotek main.o Konsolidator Kod maszynowy, jeszcze nie gotowy do uruchomienia Dołączenie kodu z bibliotek standardowych i innych zewnętrznych main.exe Program wykonywalny Copyright Roman Simiński Strona : 63

Kompilacja + konsolidacja dla programu wielomodułowego problem main.cpp Wersja źródłowa iostream cstdlib fun.hpp Preprocesor main.cpp po preprocesingu Realizacja dyrektyw, w tym #include Plik tekstowy po rozwinięciu dyrektyw preprocesora Kompilator Kompilacja, generacja kodu maszynowego main.o Kod maszynowy, jeszcze nie gotowy do uruchomienia Pliki bibliotek Konsolidator Dołączenie kodu z bibliotek standardowych i innych zewnętrznych Skąd konsolidator ma wiedzieć, że funkcje są w fun.cpp? main.exe Program wykonywalny Copyright Roman Simiński Strona : 64

Kompilacja rozłączna koncepcja main.cpp fun.cpp iostream cstdlib Preprocesor Preprocesor fun.hpp fun.hpp main.cpp po preprocesingu fun.cpp po preprocesingu Kompilator Kompilator Kompilacja programu głównego main.cpp main.o fun.o Pliki bibliotek Konsolidator Dołączenie kodu z bibliotek standardowych i modułu fun.cpp main.exe Program wykonywalny Copyright Roman Simiński Strona : 65

Kompilacja rozłączna koncepcja main.cpp fun.cpp iostream cstdlib Preprocesor Preprocesor fun.hpp fun.hpp main.cpp po preprocesingu fun.cpp po preprocesingu Kompilator Kompilator main.o fun.o Kompilacja modułu fun.cpp Pliki bibliotek Konsolidator Dołączenie kodu z bibliotek standardowych i modułu fun.cpp main.exe Program wykonywalny Copyright Roman Simiński Strona : 66

Kompilacja rozłączna koncepcja main.cpp fun.cpp iostream cstdlib Preprocesor Preprocesor fun.hpp fun.hpp main.cpp po preprocesingu fun.cpp po preprocesingu Kompilator Kompilator Kod maszynowy programu głównego main.o fun.o Kod maszynowy funkcji Pliki bibliotek Konsolidator Dołączenie kodu z bibliotek standardowych i modułu fun.o main.exe Program wykonywalny Copyright Roman Simiński Strona : 67

Kompilacja rozłączna manualne zarządzanie kompilacją Załóżmy, że kompilator dostępny jest poleceniem cc (jak w systemach Unixowych) i zmienne środowiskowe są ustalone. cc test.cpp Wywołanie to spowoduje: kompilacje programu test.cpp, wygenerowanie pliku pośredniego test.o (w przypadku braku błędów), połączenie test.o z plikami bibliotek i generacja i wynikowego pliku a.out. Użycie flagi -o umożliwia określenie nazwy pliku wynikowego (np. uruchom). cc test.cpp o uruchom Użycie flagi -c pozwala na samą kompilację (bez konsolidacji programu). cc -c test.cpp Powstaje tylko plik pośredni test.o. Copyright Roman Simiński Strona : 68

Kompilacja rozłączna manualne zarządzanie kompilacją Załóżmy, że nasz program składa się z modułów: main.cpp program główny z funkcją main, fun.cpp moduł z definicjami funkcji. Kompilujemy oddzielnie poszczególne moduły: cc -c main.cpp cc -c fun.cpp Powstają pliki pośrednie main.o oraz fun.o. Łączymy je w program wykonywalny o nazwie uruchom: cc fun.o main.o o uruchom W przypadku modyfikacji pliku fun.cpp wystarczy: cc -c fun.cpp cc fun.o main.o o uruchom Copyright Roman Simiński Strona : 69

Kompilacja rozłączna automatyzacja make program realizujący niezbędne kompilacje w oparciu o reguły zdefiniowane w pliku sterującym (domyślna nazwa Makefile): plik ten opisuje zależności pomiędzy modułami programu oraz określa jaki wywołania powinny zostać wykonane dla każdego z modułów, program make sprawdza czasy modyfikacji plików źródłowych i docelowych i przeprowadza jedynie niezbędne kompilacje. Makefile dla omawianego przykładu: uruchom : fun.o main.o cc fun.o main.o o uruchom fun.o : fun.cpp fun.hpp cc -c fun.cpp main.o : main.cpp fun.hpp cc -c main.cpp Copyright Roman Simiński Strona : 70

Kompilacja rozłączna tworzenie projektów w środowiskach IDE Większość środowisk programistycznych oferuje możliwość budowania projektów. Projekt określa przynajmniej: pliki źródłowe i pomocnicze wchodzące w skład programu, lokalizację bibliotek, plików nagłówkowych, opcje kompilacji, typ kodu wynikowego, oraz inne, zależne od implementacji, cechy i parametry programu. Copyright Roman Simiński Strona : 71

Kompilacja rozłączna tworzenie projektów w Code::Blocks Copyright Roman Simiński Strona : 72

Kompilacja rozłączna tworzenie projektów w Dev-C++ Copyright Roman Simiński Strona : 73

Co może eksportować moduł? Stałe, jako symbole preprocesora: #define KEY_UP 0x48 #define KEY_DOWN 0x50 #define KEY_LEFT 0x4b #define KEY_RIGHT 0x4d Typy wyliczeniowe: enum ctrl_key_codes KEY_UP = 0x48, KEY_DOWN = 0x50, KEY_LEFT = 0x4b, KEY_RIGHT = 0x4d ; Nazwy typów zdefiniowanych przez programistę: typedef unsigned char typedef unsigned short int typedef unsigned long int byte; word; counter_t; Copyright Roman Simiński Strona : 74

Co może eksportować moduł? cd.... Definicje zmiennych const: const int MAKS_PREDK_ZABUD = 50; const double MOJE_PI = 3.14; Prototypy funkcji: double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); Uwaga, jeżeli moduł eksportuje definicje typów czy stałych, zwykle trzeba zabezpieczać plik nagłówkowy przed wielokrotnym włączaniem w tym samym zakresie. Copyright Roman Simiński Strona : 75

Zabezpieczenie przed wielokrotnym włączaniem pliku nagłówkowego Dyrektywa kompilacji warunkowej: #ifndef _fun_hpp_ #define _fun_hpp_ const double MOJE_PI = 3.14; double pole_kwadratu( double bok );... #endif #include "fun.hpp".. #include "fun.hpp".. #include "fun.hpp" Gdyby nie było tej dyrektywy: const double MOJE_PI = 3.14; double pole_kwadratu( double bok );... #include "fun.hpp".. #include "fun.hpp".. #include "fun.hpp" Copyright Roman Simiński Strona : 76

Eksport zmiennej zewnętrznej Uwaga, jeżeli moduł ma eksportować zmienną, należy w odpowiedni sposób to opisać. Deklaracja zmiennej informacja o typie i nazwie zmiennej, nie musi zawierać informacji o klasie pamięci i wartości incjalizującej. Definicja zmiennej to deklaracja zawierająca informacje o klasie pamięci i wartości inicjalizującej. Definicja zmiennej występuje raz i rezerwuje pamięć dla zmiennej, zgodna z definicją deklaracja może występować w programie wiele razy, ma charakter informacyjny. Copyright Roman Simiński Strona : 77

Eksport zmiennej zewnętrznej Plik nagłówkowy zawiera deklarację zmiennej: extern int input_data_error; Plik implementacyjny zawiera definicję zmiennej: int input_data_error; #ifndef _fun_hpp_ #define _fun_hpp_ extern int input_data_error; double pole_kwadratu( double bok ); double obwod_kwadratu( double bok ); double pole_kola( double promien ); double obwod_kola( double promien ); #endif #include "fun.hpp" #include <cmath> int input_data_error; double pole_kwadratu( double bok ) return bok * bok;... Copyright Roman Simiński Strona : 78

Każda funkcja i zmienna zewnętrzna jest domyślnie eksportowana Każda funkcja i zmienna zewnętrzna występująca w module może być dostępna dla innych modułów programu. Czasem chcemy jednak ograniczyć dostęp do takich zmiennych i funkcji uprywatnić je w obrębie modułu. Jeżeli definicja zmiennej zewnętrznej lub funkcji zawiera słowo static, nie są one dostępne dla innych modułów programu: static int private_error_flag;... static void private_error_handler( void )... Nazwy takich zmiennych i funkcji mogą się powtarzać w innych modułach programu. Copyright Roman Simiński Strona : 79