650 likes | 849 Views
Język C. Michał Małafiejski mima@sphere.pl. Nic nie jest tak proste, by nie można było wykonać tego źle Prawo Murphy’ego. Plan wykładu (propozycja).
E N D
Język C Michał Małafiejski mima@sphere.pl Nic nie jest tak proste, by nie można było wykonać tego źle Prawo Murphy’ego
Plan wykładu (propozycja) • wykład I(6): standard ANSI C, proste programy, podstawowe opcje kompilatora, składnia i semantyka języka C, instrukcje przypisania, bloki instrukcji, instrukcje sterujące (pętle), instrukcje warunkowe • wykład II(4): wyrażenia i operatory arytmetyczne, kolejność wykonywania obliczeń w wyrażeniach, typy danych, konwersja typów, definicja struktur • wykład III(4): operacje na plikach, formatowane wejście oraz wyjście, funkcje i struktura programu, zasięg nazw, pliki nagłówkowe, preprocesor języka C, kompilacja warunkowa • wykład IV(4): wskaźniki i tablice, arytmetyka na adresach, związki tablic i wskaźników, tablice znakowe, wskaźniki do funkcji, struktury i funkcje, skomplikowane deklaracje, unie i pola bitowe • wykład V(6): struktury i funkcje rekursywne, abstrakcyjne typy danych i ich implementacje: stos, kolejka, listy, drzewa • wykład VI(1)*: przegląd funkcji bibliotek standardowych języka C, biblioteki: wejścia/wyjścia, funkcji matematycznych, operacji na tekstach i łańcuchach *: dla studiów dziennych
Zasady • kontakt: • email: mima@sphere.pl • GG: 2590739 • wykład kończy się egzaminem pisemnym (test + zadania) • ocena 5.0 z laboratorium zwalnia z egzaminu z oceną 4.0 • pomoce: • Brian W. Kernighan, Dennis M.Ritchie, Język ANSI C, WNT (2002) • kurs oraz opis bibliotek standardowych: http://binboy.sphere.pl dział Programowanie / ANSI C • testowanie umiejętności programistycznych (zadania) http://pl.spoj.pl
Plan wykładu I • Biblioteki standardowe • Trzeci program • Jednostki leksykalne • Strukturalizacja • Instrukcja warunkowa • Instrukcja wyboru • Instrukcje powtarzania • Przykłady • Zasady • Historia języka C • Standard ANSI C • Pierwszy program • Struktura programu • Kompilacja i uruchomienie • Opcje kompilatora • Drugi program
Historia języka C • Poprzednikiem języka C był interpretowany język B który Ritchie rozwinął w język C. Pierwszy okres rozwoju języka to lata 1969-1973. • W roku 1973 w języku C udało się zaimplementować jądra (kernel) systemu operacyjnego Unix. W 1978 roku Brian Kernighan i Dennis Ritchie opublikowali dokumentację języka p.t. C Programming Language. • C stał się popularny poza Laboratoriami Bella (gdzie powstał) po 1980 roku i stał się dominującym językiem do programowania systemów operacyjnych i aplikacji. Na bazie języka C w latach osiemdziesiątych Bjarne Stroustrup stworzył język C++, który wprowadza możliwość programowania obiektowego.
Standard ANSI C • Pierwsze wersje systemu UNIX były rozpowszechniane w szkołach wyższych wraz z pełnym kodem źródłowym napisanym w języku C. • Potrzeba stworzenia standardu języka wynikała z jego popularności - coraz więcej osób z niego korzystało (głównie na uniwersytetach). • Amerykański standard języka - ANSI C (1983-1988). • Stanowił on znaczne rozszerzenie w stosunku do wersji Kernighan'a i Ritchie'go. • Kolejna wersja standardu języka: ISO 9899:1990 - modyfikacja standardu ANSI. Język zgodny z tą wersją standardu określany jest nieformalnie jako C89. Od tego czasu powstało wiele uaktualnień tej normy (np. powszechnie obowiązująca C99).
Standard ANSI C (2) • W języku C zawarte są podstawowe instrukcje sterujące, niezbędne w programowaniu strukturalnym: • „wykonuj jeden po drugim”: grupowanie instrukcji (nawiasy klamrowe { }) • „wykonuj dla wszystkich”, „wykonuj aż do”: powtarzanie ze sprawdzeniem warunku zatrzymania (pętle for, while) • „wybierz z”: podejmowanie decyzji (if - else) • Możliwość tworzenia funkcji w języku C – wydzielanie (powtarzalnych) fragmentów programu – kolejne wsparcie dla strukturalizacji. • Język C jest językiem niskiego poziomu: duża część kodu języka C jest bezpośrednio tłumaczona na język wewnętrzny komputera (operacje na adresach, znakach i liczbach).
Standard ANSI C (3) • Standard języka C miał na celu zagwarantowanie poprawności (istniejących oraz przyszłych) programów – bez względu na architekturę komputera. • Standard definiuje konstrukcje języka, jego składnię oraz zawiera specyfikacje funkcji standardowej biblioteki. • W stosunku do pierwszych wersji języka C, standard ANSI C wprowadził kilka istotnych rozszerzeń: • deklaracje funkcji mogły zawierać opis parametrów, • specyfikacja bibliotek towarzyszących C • funkcje odwołujące się do systemu operacyjnego • operacje na pamięci • funkcje matematyczne • operacje na plikach (realizacja wejścia – wyjścia)
Pierwszy program kod źródłowy 1: #include<stdio.h> 2: intmain() 3: { 4: printf(„Witaj przyjacielu!\n”); 5: return0; 6: } • kod źródłowy składa się z dyrektyw preprocesora (include), słów kluczowych (int, return) oraz nazw funkcji (main, printf) i ich argumentów (w nawiasach), nawiasy klamrowe grupują wiele instrukcji
Pierwszy program (2) 1: #include<stdio.h> dyrektywa informująca kompilator o wykorzystaniu funkcji z biblioteki standardowej stdio.h 2: intmain() nagłówek funkcji głównej programu (w każdym programie musi znaleźć się funkcja main), typ zwracanej wartości–całkowity (int) 3: { nawias otwierający blok instrukcji – ciało funkcji głównej main 4: printf(„Witaj przyjacielu!\n”); funkcja z biblioteki standardowej stdio.h – wydrukowanie podanego w nawiasie napisu na standardowe wyjście 5: return0; zwrócenie wartości 0 (funkcja ma typ całkowity int) 6: } nawias zamykający blok instrukcji – ciało funkcji głównej main
Struktura programu • Kod programu może zostać umieszczony w jednym bądź kilku plikach. • Program składa się z dyrektyw preprocesora, definicji struktur, funkcji oraz zmiennych. • Funkcje zbudowane są z instrukcji. • Instrukcje składają się ze słów kluczowych, operatorów, nazw zmiennych oraz znaków grupujących i separujących (nawiasy, przecinki, średniki). • Program zaczyna działanie od wykonania funkcji main. • Pozostałe funkcje mogą być napisane przez programistę lub pochodzić z bibliotek. • Przed uruchomieniem program należy skompilować i scalić z funkcjami bibliotecznymi.
Kompilacja i uruchomienie • Po skończeniu edycji kodu źródłowego zapisujemy tekst do pliku (nazwa dowolna, rozszerzenie .c): first.c • Kompilacja, czyli przetłumaczenie kodu źródłowego na postać binarną zrozumiałą dla komputera (ale jeszcze nie wykonywalną): • poleceniem gcc –c first.c tworzymy plik first.o • Scalanie, czyli połączenie skompilowanego kodu naszego programu oraz funkcji z bibliotek zewnętrznych (np. standardowych): • poleceniem gcc –o firstfirst.o tworzymy plik wykonywalny first • kompilację oraz scalanie: jednym poleceniem gccfirst.c tworzymy plik wykonywalny a.out
Kompilacja i uruchomienie (2) biblioteki funkcja printf • wykonanie programu: polecenie ./first (lub first) • pod Windowsem: first.exe (zamiast first) first.c first.o first kompilacja scalanie
Opcje kompilatora • składnia polecenia: gccopcje nazwy_plików • brak opcji: kompilacja i scalanie, standardowa nazwa pliku wykonywalnego a.out • -c - tylko kompilacja • -oname – utworzenie pliku wykonywalnego o nazwie name • -ansi – sprawdzenie kodu pod kątem zgodności ze standardem ANSI • -Wall – pokazanie wszystkich ostrzeżeń podczas kompilacji (ostrzeżenia (warnings) nie przerywają procesu kompilacji, w przeciwieństwie do błędów (errors))
Drugi program kod źródłowy 1: #include<stdio.h> 2: intmain() { /* (i): usuń int */ 3: inta; /* (ii): wstaw: ,b */ 4: scanf(„%d”, &a); 5: printf(„%d * %d = %d\n”, a, a, a*a); 6: return0; /* (iii): zakomentuj linię */ 7: } kompilacja: -ansi -Wall
Drugi program (2) 1: funkcje biblioteczne scanf oraz printf realizują sformatowane operacje wejścia – wyjścia (odczyt – zapis) 2: format wejścia – czyli kolejność oraz typy danych, które pojawiają się na wejściu – opisany jest w nawiasie, np.: scanf(„%d”, &a) oznacza wczytanie z wejścia liczby całkowitej oraz zapisanie jej wartości do komórki (zmiennej) o nazwie a 3: kolejne opisy pól z formatu wejścia oddzielamy przecinkami, wartość przypisana w danym miejscu może zostać wyznaczona z dowolnego poprawnego wyrażenia (zmienne wraz z operacjami na nich)
Drugi program (3) (i): kompilacja kodu źródłowego z parametrem –ansi –Wall spowoduje wygenerowanie ostrzeżenia: second.c:2: warning: return type defaults to `int' (ii) zmienna b nie jest nigdzie wykorzystana, stąd kompilator zgłosi ostrzeżenie: second.c :3: warning: unused variable `b‘ (iii) brak zwracanej wartości kompilator odnotuje: second.c :7: warning: control reaches end of non-void function
Biblioteki standardowe • assert.h – diagnozowanie programów • ctype.h – klasyfikacja znaków • errno.h – zmienne przechowujące informacje o błędach • math.h – funkcje matematyczne • signal.h – mechanizmy obsługi zdarzeń wyjątkowych • stdio.h – funkcje wejścia oraz wyjścia • stdlib.h – funkcje narzędziowe (przekształcanie liczb, operacje na pamięci) • string.h – operacje na tekstach • time.h – obsługa daty oraz czasu
Biblioteki standardowe (2) • Biblioteka math – przykłady funkcji • doublesin(doublex); • floatsinf(floatx); • doubleexp(doublex); • doublelog(doublex); • doublepow(doublex, doubley); • Biblioteki stdlib oraz string – przykłady funkcji • intatoi(const char*nptr); • longatol(const char*nptr); • char*strcat(char*dest, const char*src);
Trzeci program 1: #include<stdio.h> 2: #include<math.h> 3: #include<stdlib.h> 3: intmain() { 4: doublea = 2; 5: char*liczba = „123”; 5: printf(„%f\n”, exp(a)); 6: printf(„%d\n”, atoi(liczba)); 7: return0; 8: } kompilacja: -ansi –Wall -lm
Trzeci program (2) 1: parametr –lm „podpowiada” programowi scalającemu, że powinien wykorzystać bibliotekę matematyczą 2: printf(„%f\n”, exp(a)); wydrukowanie wartości exp(2) 3: printf(„%d\n”, atoi(liczba)); konwersja łańcucha znaków „123” do formatu liczby całkowitej 123
Jednostki leksykalne - identyfikatory • Jednostki leksykalne są to niezależne, oddzielone separatorami (spacje, średnik, przecinek) fragmenty kodu źródłowego, np. int (typ zmiennej), scanf (identyfikator – nazwa funkcji), for, while (słowa kluczowe) • Identyfikatory są to nazwy zmiennych lub funkcji. • Identyfikator jest sekwencją liter i cyfr oraz znaków podkreślenia (‘_’). • Rozróżniane sa małe oraz duże litery. • Pierwszy znak nie może być cyfrą. • Należy unikać stosowania nazw zaczynających się od ‘_’ (zarezerwowane dla bibliotek).
Jednostki leksykalne – słowa kluczowe • Podane poniżej identyfikatory są słowami kluczowymi (zarezerwowane dla języka C): • char, int, float, double, enum, void • long, short, signed, unsigned • const, static, volatile, extern, register, struct, union • for, while, do, switch, case, default, if, else • break, continue, return, goto, inline, sizeof, typedef
Strukturalizacja - sterowanie • „wykonuj jeden po drugim”: grupowanie instrukcji (nawiasy klamrowe { }) • „wykonuj dla wszystkich”, „wykonuj aż do”: powtarzanie ze sprawdzeniem warunku zatrzymania (pętle for, while) • „wybierz z”: podejmowanie decyzji (if - else)
Strukturalizacja • Instrukcja: wyrażenie zakończone średnikiem, np. • x = 0; • printf(„Hello!”); • return 1; • Nawiasy klamrowe służa do grupowania instrukcji w instrukcję złożoną, czyli blok np. { x = 0; printf(„Hello!”); } • instrukcje dzielimy na: • instrukcje przypisania (=) • instrukcje warunkowe (if-else) • instrukcje wyboru (switch-case) • instrukcje powtarzania (pętle: for, while)
Instrukcja warunkowa if( wyrażenie ) instrukcja1 else instrukcja2 • Sprawdzana jest wartość wyrażenia, w przypadku gdy jest różna od zera wykonywana jest instrukcja1, w przeciwnym wypadku – instrukcja2 • instrukcja1 może być instrukcją prostą lub złożoną
Program Warunek Trójkąta Problem: Napisać program sprawdzający czy z podanych trzech długości można zbudować trójkąt. Wejście: liczby całkowite: a, b, c Wyjście: odpowiedź TAK lub NIE Rozwiązanie: 1. Wczytujemy 3 liczby ze standardowego wejścia 2. Należy sprawdzić warunki: a + b > c a + c > b b + c > a 3. Jeżeli wszystkie warunki są spełnione, drukujemy TAK,w przeciwnym razie drukujemy NIE (na wyjście)
Program Warunek Trójkąta 1: #include<stdio.h> 2: intmain() { 3: int a, b, c; 4: scanf(„%d%d%d”, &a, &b, &c); 5: if( a + b > c ) if( b + c > a ) if( a + c > b ) printf(„TAK”); elseprintf(„NIE”); elseprintf(„NIE”); elseprintf(„NIE”); 7: return0; 8: }
Program Warunek Trójkąta 1: #include<stdio.h> 2: intmain() { 3: int a, b, c; 4: scanf(„%d%d%d”, &a, &b, &c); 5: if(( a + b > c ) && ( b + c > a ) && ( a + c > b )) printf(„TAK”); elseprintf(„NIE”); 7: return0; 8: } zastąpienie kolejnych warunków jednym, spójnik logiczny && = AND (logiczne „i”)
Instrukcja wyboru switch( wyrażenie ) { case etykieta1: instrukcje case etykieta2: instrukcje ........ default instrukcje } Wyrażenie użyte jako selektor wyboru musi przyjmować wartości całkowite, etykiety muszą być stałymi całkowitymi. Wykonanie instrukcji switch-case: • Wyrażenie porównywane jest kolejno z etykietami, jeżeli jedna z etykiet ma wartość wyrażenia, to wykonywane są instrukcje po niej następujące. • Instrukcje po etykiecie default są wykonywane, jeżeli żadna z etykiet nie ma wartośći równej selektorowi wyboru. • Aby uniknąć sprawdzania kolejnych przypadków, stosujemy instrukcję break.
Instrukcja wyboru - przykład 1: #include<stdio.h> 2: intmain() { 3: int cyfra_mala = 0, cyfra_duza = 0, inne = 0; 4: char znak; 5: do{ /* instrukcja powtarzania */ 6: scanf(„%c”, &znak); 7:switch( znak ) { /* instrukcja wyboru */ 8: case‘0’: case‘1’: case‘2’: case‘3’: case‘4’: 9: cyfra_mala++; break; 10: case‘5’: case‘6’: case‘7’: case‘8’: case‘9’: 11: cyfra_duza++; break; 12: default: inne++; 13: } 14: }while (znak != EOF ); 15: printf(„%d %d %d”, cyfra_mala, cyfra_duza, inne); 16: return0; 17: }
Instrukcje powtarzania while ( wyrażenie ) instrukcja do instrukcja while ( wyrażenie ) for ( W1; W2; W3 ) instrukcja
Instrukcje powtarzania - zadania • Napisz program, który wyznacza wartość: n! = 1 · 2 · ... ·n • Napisz program, który drukuje trójkąt z gwiazdek: * *** ***** ******* 3. Napisz program, który wczytuje ze standardowego wejścia kolejne znaki – cyfry i tworzy z nich liczbę dziesiętną.
Plan wykładu II • Proste typy danych • Stałe • Deklaracje • Operatory i wyrażenia • Kolejność wykonywania obliczeń w wyrażeniach • Proste funkcje • Konwersja typów • Definicja struktur • Odwrotna Notacja Polska* *: dla studiów dziennych (wymagane na egzaminie)
Proste typy danych • W języku C wsytępuje tylko kilka podstawowych typów danych: • char jeden bajt, typ znakowy • int typ cakowity, standard ANSI określa rozmiar na co najmniej dwa bajty • float typ zmiennoprzecinkowy pojednycznej precyzji • double typ zmiennoprzecinkowy podwójnej precyzji • Kwalifikatory short (krótki, nie dłuższy niż int) oraz long (długi, przynajmniej 4 bajty) odnoszą się do obiektów całkowitych, np.: • short int a; • long int b; lub zmiennoprzecinkowych, np.: • long double c; • Kwalifikatory signed (ze znakiem liczby) oraz unsigned (bez znaku liczby) można stosować z typem char lub dowolnym typem całkowitym, np.: • signed char znak; /* od –128 do 127 */ • unsigned char; /* od 0 do 255 */
Tablice oraz wskaźniki (wstęp) • Jeżeli chcemy utworzyć zmienną, która będzie przechowywać wiele wartości danego typu prostego deklarujemy tablicę, czyli obszar pamięci złożony z podanej w nawiasie liczby komórek, z którego każda jest zadanego typu prostego (uwaga: można tworzyć tablice tablic) • int a[10]; • float tab[15]; • Jeżeli nie znamy rozmiaru tablicy możemy utworzyć zmienną wskaźnikową • int* a; • float* b; Uwaga! Deklaracja zmienne wskaźnikowej nie powoduje zarezerwowania dla niej pamięci!
Stałe • Każda stała jest jakiegoś typu (np. występująca w wyrażeniach). • Stałe całkowite • 1234 domyślnie typu int • 1234L typu long int • 1234U unsigned int • 1234UL unsigned long int • 012 system ósemkowy = 10 • 0x12 system szesnastkowy = 18 • Stałe zmiennoprzecinkowe • notacja dziesiętna z kropką: -314.15 • notacja wykładnicza: -3.1415e2 (lub –3.1415E2) • domyślnie typu double • użycie literki F lub L zmienia typ na float lub long double • Stałe znakowe oraz łańcuchowe • ‘a’ ujęte w pojedyncze apostrofy, typ char • „ala ma psa” ciągi znaków ujęte w apostrofy
Deklaracje • Deklaracje zmiennych • intcyfra = 7; • charznak; • charznak = ‘o’; /* deklaracja zmiennej znak wraz z inicjacją wartości */ • double a, b = 3.2e-1; • Deklaracje stałych • const double pi = 3.1415; • const int liczba = 37; Uwaga! Wartość zmiennych poprzedzonych kwalifikatorem const nie może być zmieniona w trakcie działania programu (próba zmiany: zależna od implementacji kompilatora). • Wyliczenia • enum dni {pn, wt, sr, czw, pt}; /* domyślnie: 0, 1, 2, 3, 4 */ • enum rok {smoka = 1, koguta, malpy}; /* kolejne =2, =3, ... */
Operatory i wyrażenia • Język C oferuje programiście znaczną liczbę operatorów: • operatory arytmetyczne: addytywne (+ -), multiplikatywne (* / %), inkrementacji (++) oraz dekrementacji (--) • operatory bitowe (& ^ | ~ << >>) • operatory logiczne (&& || !) • operatory relacyjne (> < <= >= == !=) • operatory przypisania (=) • operator warunkowy (? :) • operator wyliczeniowy (,) • operator wyboru składowych (. ->) • operator pobrania adresu oraz dostępu do zmiennej wskazywanej (& *) • operator pobrania rozmiaru (sizeof) • operator indeksowania ([]) • operator konwersji (nazwa-typu)
Operatory i wyrażenia • operatory arytmetyczne: addytywne (+ -), multiplikatywne (* /), inkrementacji (++) oraz dekrementacji (--) • addytywne • dodawanie a + b typy arytmetyczne • odejmowanie a – b typy arytmetyczne (a,b – operandy, +,- operatory) musi zachodzić zgodność typów, oba arytmetyczne lub jeden całkowity, a drugi wskaźnikowy • multiplikatywne • mnożenie a * b typy arytmetyczne • dzielenie a / b typy arytmetyczne • reszta modulo a % b typy całkowite • inkrementacji i dekrementacji • przedrostkowe --a ++a • przyrostkowe a-- a++ operand musi być typu arytmetycznego lub wskaźnikowego
Operatory i wyrażenia • operatory bitowe (& ^ | ~) • iloczyn AND a & b typy całkowite • suma modulo 2 EXOR a ^ b typy całkowite • alternatywa OR a | b typy całkowite • negacja NOT ~a typ całkowity przed obliczaniem wartości dokonywane są konwersje arytmetyczne Działania logiczne na bitach a b AND EXOR OR NOT 0 0 0 0 0 1 • 0 0 1 1 0 0 1 0 1 1 1 1 1 1 0 1 0 • operatory przesunięcia bitowego >> << a >> b przesuń liczbę a o b bitów w prawo a << b przesuń liczbę a o b bitów w lewo dla liczb ze znakiem przesunięcie w prawo powiela bit znaku
Operatory i wyrażenia • operatory logiczne (&& || !) • koniunkcja a && b • alternatywa a || b • negacja !a wartość wyrażenia logicznego jest zawsze typu int Tabela wartości wyrażeń logicznych a b koniunkcja alternatywa negacja 0 0 fałsz fałsz prawda • 0 fałsz prawda fałsz 0 1 fałsz prawda prawda • 1 prawda prawda fałsz • operatory warunkowy (? :) • a ? b : c w pierwszej kolejności obliczana jest wartość a, jeżeli jest ona niezerowa jest obliczana wartość b, natomiast c jest ignorowane, w przeciwnym razie (a jest równa zero) - odwrotnie
Operatory i wyrażenia • operatory relacyjne (> < <= >= == !=) • a < b a mniejsze niż b • a > b a większe niż b • a <= b a mniejsze lub równe b • a >= b a większe lub równe b • a == b a równe b • a != b a różne od b Oba operandy muszą być typu arytmetycznego lub oba wskaźnikami zgodnych typów • operatory przypisania (= oraz złożone) • a = b w przypadku róźnych typów zachodzi konwersja do typu a • złożone operatory przypisania a += b -= *= /= %= <<= >>= &= ^= |=
Operatory i wyrażenia • operator wyliczeniowy (,) a, b, c; dowolne typy Opracowywanie tego wyrażenia przebiega zgodnie z kolejnością • operator wyboru składowych (. ->) w celu odwołania się do struktury lub unii należy posłuzyć się jednym z operatorów wyboru składowej a.x a->x w zależności od typu a • operator pobrania adresu oraz dostępu do zmiennej wskazywanej (& *) • &a pobranie adresu • *a odwołanie do zmiennej wskazywanej przez a • operator pobrania rozmiaru (sizeof) • sizeof(typ) rozmiar w bajtach typu • sizeof(a) rozmiar pamięci zajmowanej przez a • operator indeksowania ([]) • a[2] (*a+2) dostęp do trzeciej komórki (liczone od 0)
Kolejność wykonywania obliczeń • Każde wyrażenie musi zostać przeanalizowane przez kompilator w celu ustalenia kolejności wykonywanych obliczeń oraz zgodności typów występujących argumentów • a + b * c (a + b) * c ? a + (b * c) • 3 / 2 1.5 ? 1 • Pierwszą rzeczą jest zatem informacja dla kompilatora, które działania mają wyższy priorytet, drugą rzeczą jest informacja o typach operandów w wyrażeniach • Podstawowe pojęcia: • priorytet operatorów stanowi o kolejności wykonywanych działań • wiązanie sposób łączenia operatora z operandami • operatory unarne (jednoargumentowe) i binarne (dwuargumentowe) • l-wyrażenia wyrażenia identyfikujące obszar pamięci, specyfikator const powoduje, że l-wartość nie jest modyfikowalna • opracowywanie wyrażenia wszystkie obliczenia i inne operacje jakie sa wykonywane podczas przetwarzania wyrażenia
Kolejność wykonywania obliczeń • Priorytety operatorów: a + b * c (a + b) * c ? a + (b * c) wyrażenie zostanie opracowane zgodnie z priorytetami operatorów + oraz *: jeżeli + będzie miał wyższy priorytet niż * wtedy dodawanie zostanie wykonane przed mnożeniem, jeżeli zaś odwrotnie, to mnożenie zostanie wykonane przed dodawaniem • Wiązanie operatorów: a + b – c (a + b) – c ? a + (b – c) jeżeli kolejność obliczeń nie została określona za pomocą nawiasów, zostanie rozstrzygnięta na podstawie wiązania jeżeli wiązanie następuje od lewej do prawej (tak jak w C), to wyrażenie zostanie potraktowane jako (a + b) – c, jeżeli od prawej do lewej, to jako a + (b – c)
Kolejność wykonywania obliczeń • Operatory unarne: operatory wymagające jednego operanda (argumentu), np. ~ (negacja binarna), ! (negacja logiczna), & (operator pobrania adresu), * (operator dostępu do zmiennej wskazywanej) • Operatory binarne: operatory dwuargumentowe, wymagające dwóch operandów, wiązanie dla wszystkich operatorów zdefiniowane jest od lewej do prawej, poza złożonymi operatorami przypisania oraz operatorem warunkowym
Proste funkcje • Podczas pisania programu (implementacji algorytmu) zachodzi potrzeba wielokrotnego wykonywania tych samych operacji (instrukcji) w różnych sytuacjach (dla różnych danych), np. znalezienie najmniejszego elementu w ciągu liczb (w szczególnym przypadku dwóch liczb), posortowanie ciągu liczb, wyznaczenie rozwiązań równania kwadratowego. • W obrębie funkcji można zamknąć operacje wykonywane dla zadanych paramtetrów wejściowych, np. ciąg liczb, współczynniki równania kwadratowego a, b, c • W praktyce każdy (większy) program jest zbudowany z wielu funkcji (dobry styl programowania, wiele krótkich i czytelnych funkcji), poprawia to przejrzystość i czytelność programu, zapewnia oszczędność czasu (funkcja raz napisana może być wielokrotnie wykorzystana), pozwala wreszcie zaoszczędzić pamięć – funkcja jest umieszczona w jednym miejscu w pamięci podczas wykonywania programu.
Proste funkcje - przykłady • Funkcja obliczająca minimum dwóch liczb a oraz b, to znaczy zwraca wartość równą mniejszej z obu liczb 1: intmin(int a, int b) { 2: if( a > b ) returnb; 3:elsereturna; 4: } • Wykorzystanie funkcji w programie: • wywołanie min(a, b) • Napisz funkcje realizujące (poniżej podano deklaracje) • liczenie silni: intsilnia(inta); • znajdującą element minimalny: intmin(int*tablica);
Funkcje – deklaracja i definicja • Deklaracja funkcji, w odróżnieniu od definicji jest pojęciem logicznym, stanowi informację dla kompilatora, że funkcja o określonej nazwie, typie parametrów może zostać użyta (ale nie musi!) w programie. intmin(int a, int b); • Definicja funkcji określa natomiast co funkcja robi, stanowi zatem zapis jakiegoś algorytmu, definicja funkcji, w odróżnieniu od deklaracji, powoduje przydzielenie obszaru pamięci, w którym znajduje się kod wynikowy funkcji. 1: intmin(int a, int b) { 2: if( a > b ) returnb; 3:elsereturna; 4: }