mgr inż. Jarosław Forenc e-mail: jarekf@pb.bialystok.pl tel. (0-85) 746-93-97 WWW: http://we.pb.bialystok.pl/~jforenc konsultacje: zaliczenie: Program wykładu: WYKŁAD 1 - KONSPEKT 1. Ogólna struktura programu w języku C. Kompilacja programu. Typy, zmienne, stałe, operatory i wyrażenia arytmetyczne. 2. Operatory relacyjne i logiczne. Instrukcja warunkowa if, instrukcja wyboru switch. 3. Instrukcje iteracyjne: for, while, do... while. 4. Tablice i wskaźniki. 5. Łańcuchy znaków, struktury, unie, pola bitowe. 6. Funkcje, przekazywanie argumentów do funkcji. 7. Pliki. Literatura: 1. B.W. Kernighan, D.M. Ritchie: Język ANSI C, WNT, Warszawa, 2004. 2. C.L. Tondo, S.E. Gimpel: Język ANSI C. Ćwiczenia i rozwiązania, WNT, Warszawa, 2004. 3. G. Perry: Język C w przykładach, Mikom, Warszawa, 2000. 4. H. Schildt: Język C, LTP Oficyna Wydawnicza, 2002. 5. S. Oulline: Język C. Programowanie, Helion, Gliwice, 2003. 6. J. Bielecki: Encyklopedia języka C dla IBM PC, tom 1,2, WNT, Warszawa, 1989. Historia języka C 1969 Martin Richards (University Mathematical Laboratories, Cambridge) definiuje język BCPL, 1970 Ken Thompson definiuje język B będący adaptacją języka BCPL dla pierwszej instalacji systemu operacyjnego Unix na komputer DEC PDP-7, 1972 Dennis Ritchie z Bell Laboratories w New Jersey definiuje język C dla systemu Unix działającego na komputerze DEC PDP-11 (w języku tym zostaje napisane ok. 90 % kodu systemu i większość programów działających pod jego kontrolą), 1978 Ukazuje się książka B.W. Kernighan, D.M. Ritchie: The C Programming Language opisująca język C, 1983 Amerykański Narodowy Instytut Standaryzacji (ANSI) powołuje komitet, którego zadaniem ma być sformułowanie nowoczesnej, wszechstronnej definicji języka C, 1988 Komitet kończy prace nad opracowaniem standardu ANSI zwanego ANSI C.
Program w języku C Program w języku C jest to niesformatowany plik tekstowy o odpowiedniej składni mający rozszerzenie.c. Najprostszy program ma następującą postać: Przykład 1 (program wyświetlający na ekranie tekst: Witaj swiecie ) dyrektywa preprocesora nazwa pliku nagłówkowego typ wartości zwracanej przez funkcję nazwa funkcji lista argumentów przekazywanych do funkcji printf( Witaj swiecie\n ); wartość zwracana przez funkcję instrukcja instrukcja nagłówek funkcji ciało funkcji Program w języku C składa się z funkcji i zmiennych. Funkcje zawierają instrukcje określające wykonywane operacje, zaś zmienne przechowują wartości wykorzystywane podczas tych operacji. Powyższy program składa się z jednej funkcji (main), nie ma w nim natomiast zmiennych. Funkcja main składa się z dwóch instrukcji: printf i return. Każda instrukcja zakończona jest średnikiem. W programie może być zdefiniowanych więcej funkcji, ale zawsze musi istnieć funkcja o nazwie main, gdyż pełni ona szczególna rolę w programie - od początku tej funkcji rozpoczyna się wykonanie całego programu. Funkcja w języku C rozpoczyna się od nagłówka funkcji (pierwszy wiersz). Zawartość funkcji ograniczona jest nawiasami klamrowymi:, i nazywana jest ciałem funkcji. Nagłówek funkcji i ciało funkcji tworzą definicję funkcji. Język C rozróżnia wielkość liter, zatem nazwę funkcji main nie możemy zapisać jako, np. Main lub MAIN. Podobnie jest z nazwami pozostałych funkcji i słów kluczowych języka C. Zazwyczaj w programie poza funkcją main występują inne funkcje - mogą to być funkcje napisane przez nas lub funkcje pochodzące z bibliotek. W powyższym programie do wyświetlenia tekstu wykorzystywana jest funkcja o nazwie printf. Skorzystanie z tej funkcji wymaga dołączenia do naszego programu informacji o bibliotece, w której funkcja ta została zdefiniowana. Służy do tego pierwsza linia programu:. stdio.h jest to standardowa biblioteka wejścia/wyjścia (ang. standard input/output library). Funkcję wywołuje się podając jej nazwę (printf) i (w nawiasach zwykłych) listę argumentów przekazywanych do funkcji ( Witaj swiecie\n ). W powyższym przykładzie do funkcji main nie są przekazywane żadne argumenty, informują o tym puste nawiasy - ( ). Ciąg znaków ujęty w cudzysłowu nazywa się stałą napisową (napisem, łańcuchem znaków). W powyższym łańcuchu znaków na samym końcu występuje sekwencja \n - reprezentuje ona znak nowego wiersza (jest to jeden znak). Inaczej mówiąc powoduje ona przerwanie wypisywania tekstu w bieżącym wierszu i wznowienie wypisywania od lewego marginesu w następnym wierszu.
Przykłady: printf( Witaj swiecie\n ); Witaj swiecie printf( Witaj\nswiecie\n ); Witaj swiecie printf( Witaj ); printf( swiecie ); printf( \n ); Witaj swiecie Sposób zapisu kodu programu wpływa tylko na jego przejrzystość, a nie na wykonanie. W tym celu w programie występują dodatkowe spacje przed funkcją printf i słowem kluczowym return. Powyższy program można zapisać także tak: #include<stdio.h> printf( Witaj swiecie\n );return(0); Kompilacja programu Kodu programu nie można wykonać, należy go wcześniej skompilować do postaci zrozumiałej dla komputera. Proces kompilacji programu składa się z kilku etapów. Najczęściej są one niezauważalne dla programisty. Etapy te tworzą: 1. Prekompilacja (ang. preprocessing) - stworzenie ostatecznego tekstu programu źródłowego przez dołączenie plików wskazanych dyrektywą #include, wykonanie podstawień #define i opcjonalne usunięcie komentarzy. (*.c *.c) 2. Kompilacja do kodu asemblera (ang. compilation) - kompilator przeglądając kod źródłowy programu wyszukuje słowa kluczowe i operatory, a następnie przekształca je na wewnętrzną reprezentację. Następnie reprezentacja wewnętrzna jest przekształcana na kod asemblera. (*.c *.s) 3. Optymalizacja kodu asemblera (ang. optimization) - zmiana kodu asemblera w celu zwiększenia jego efektywności. Modyfikacje te polegają na: zmianie sposobu obliczania adresów względnych, eliminacji nieużywanych fragmentów kodu, optymalizacji przydziału rejestrów. Ten etap kompilacji jest opcjonalny. (*.s *.s) 4. Asemblacja (ang. assembly) - przetworzenie kodu asemblera w relokowalny kod w języku maszynowym. Instrukcje w tym kodzie nie odnoszą się jeszcze do konkretnych adresów w pamięci. Kod umieszczany jest w pliku obiektowym (ang. object file - pliki z rozszerzeniem.o lub.obj). (*.s *.o) 5. Konsolidacja (ang. link editing) - konsolidator (ang. link editor - linker) dokonuje szeregu operacji w celu stworzenia pliku binarnego z kodem wykonywalnym (*.o *.exe): - przeszukanie standardowego zestawu bibliotek oraz bibliotek wskazanych w linii wywołania w celu dołączenia do programu kodu funkcji niezdefiniowanych w modułach stworzonych przez użytkownika (np. funkcji printf),
- przypisanie kodu maszynowego do ustalonych adresów, np. zmienne globalne otrzymują konkretne adresy tak, aby można było odwoływać się do ich wartości, - utworzenie wykonywalnego pliku binarnego. Przykład 2 (program zamieniający temperaturę podaną w skali Fahrenheita na temperaturę w skali Celsjusza) Jak ma działać program? 1. Użytkownik podaje temperaturę w skali Fahrenheita. 2. Program oblicza temperaturę w skali Celsjusza według wzoru: c = (5/9)(f-32). 3. Program wyświetla obliczoną temperaturę w skali Celsjusza. W programie będą występowały dwie wartości (temperatura w skali Fahrenheita i temperatura w skali Celsjusza) zatem musimy wprowadzić dwie zmienne. 1 float tempf; /* temp. w skali Fahrenheita */ 2 float tempc; /* temp. w skali Celsjusza */ 3 4 5 6 printf( Podaj temperature w skali Fahrenheita: ); scanf( %f,&tempf); tempc=5*(tempf-32)/9; printf( Temperatura w skali Celsjusza to %f\n,tempc); 1 - Dołączenie pliku nagłówkowego stdio.h zawierającego opis funkcji printf i scanf. 2 - Deklaracja dwóch zmiennych: tempf i tempc będących liczbami rzeczywistymi (typ float). 3 - Wyświetlenie napisu: Podaj temperature... bez znaku \n na końcu. 4 - Wczytanie temperatury w skali Fahrenheita: tempf - nazwa zmiennej, &tempf - adres zmiennej (funkcja scanf wymaga podania adresu zmiennej, a nie jej nazwy), %f - określa typ wczytywanej zmiennej (%f - typ float). 5 - Obliczenie wartości wyrażenia arytmetycznego. 6 - Wyświetlenie wyniku, łańcucha znaków Temperatura w skali... i wartości zmiennej tempc. W miejscu, w którym ma być wyświetlona wartość zmiennej podajemy specyfikator formatu - %f, będzie on zastąpiony podczas wyświetlania wartością zmiennej, której nazwę podajemy po cudzysłowie kończącym łańcuch znaków i po przecinku.
Przykład 3 (program z Przykładu 2 z zastosowaniem dodatkowej funkcji) 1 float temperatura(float tf); /* prototyp funkcji */ float tempf; /* temp. w skali Fahrenheita */ float tempc; /* temp. w skali Celsjusza */ 2 printf( Podaj temperature w skali Fahrenheita: ); scanf( %f,&tempf); tempc=temperatura(tempf); printf( Temperatura w skali Celsjusza to %f\n,tempc); float temperatura (float tf) 3 float tc; 4 5 tc=5*(tf-32)/9; return tc; W powyższym programie zamianę temperatury ze skali Fahrenheita na temperaturę w skali Celsjusza umieszczono w dodatkowej funkcji o nazwie temperatura. Ponieważ funkcja ta została zdefiniowana za funkcją main (w której jest wywoływana), to na początku programu należy umieścić jej prototyp (1). Prototyp funkcji jest to nagłówek funkcji zakończony znakiem średnika. Prototyp funkcji jest informacją dla kompilatora, mówiącą że funkcja zostanie zdefiniowana później. Wykonanie całego programu rozpoczyna się od funkcji main. Gdy dochodzimy do wywołania funkcji temperatura (2), to sterowanie przekazywane jest z funkcji main do początku funkcji temperatura. Zmienna tf otrzymuje taką samą wartość jaką ma zmienna tempf w funkcji main. W funkcji temperatura deklarujemy dodatkową zmienną tc (3), a następnie obliczamy wartość temperatury w skali Celsjusza (4). Funkcja zwraca wartość obliczonej temperatury (5) do funkcji main. Zwrócona wartość podstawiana jest pod zmienną tempc. Dalej wykonanie programu przebiega podobnie jak w poprzednim przykładzie.