Wyklady PP


Wykład #1
3 marca 2010
" Przemysław Gawrooski:
D-10 p. 234
" 5 z laboratorium zwalnia z egzaminu.
" ocena koocowa - średnia arytmetyczna z lab i z egzaminu
" Egzamin:
- I termin - 29.06 1000-1200, D-10, sala A.
- II termin - 1.09 1000
" Literatura:
- Stephen Prata: "Język C: szkoła programowania"
- Herbert Schildt: "Programowanie C" - tłum. 4. wydania
- Steve Oualline: "Język C. Programowanie"
- Kenneth A. Reek: "Język C: wskazniki: vademecum profesjonalisty"
- Kyle Loudon: "Algorytmy w C"
- Brian W. Kernighan, Dennis Ritchie: "Język ANSI C"
" Teoria rozwiązywania problemów George'a Poly'a
- zrozumienie problemu,
- wymyślenie planu postępowania,
- wykonanie planu,
- weryfikacja
" Programowanie:
- projektowanie,
- tworzenie,
- testowanie
" Fajne statystyki: tiobe.com
" C - język niskopoziomowy; zwięzły; nierestrykcyjny.
" W C w dużej mierze jest napisane jądro Linuksa
" www.ioccc.org - strona konkursu na najbardziej nieczytelny kod zródłowy
" Skompilowany program w C tworzy 4 osobne obszary pamięci:
- kod wykonywalny programu
- zmienne globalne
- stos
- sterta
" C jest case-sensitive
" W C++ w liście argumentów funkcji, jeśli w nawiasach nie ma nic, to jest void. W C natomiast
wtedy nie wiem co tam jest (a może coś byd).
" Edytory tekstu pod Windows: ultraedit
Wykład # Strona 1
Wykład #2
10 marca 2010
14:03
STRUKTURA PROGRAMU
" W pliku nagłówkowym znajdują się:
1) prototypy funkcji,
2) deklaracje zmiennych zewnętrznych (extern),
3) definicje makr, struktur, typów
" Plik nagłówkowy - nazwa.c zawiera:
1) zasadniczą treśd programu
2) wiele plików *.c - modułowa budowa programu
" Argumenty funkcji głównej (main())
int main(int argc, char *argv[])
int argc - liczba parametrów wywołania
argv[0] - łaocuch zawierający pełną ścieżkę dostępu do uruchomionej aplikacji, pozostałe
elementy to wskazniki łaocuchów zawierających kolejne parametry wywołania,
konwersja char na int np. poprzez funkcję atoi()
KOMPILACJA, KONSOLIDACJA, WYKONANIE
" Wybrane parametry kompilatora gcc:
- -c mówi że ma tylko skompilowad,
- -Wall wypisuje wszystkie ostrzeżenia,
- -o powoduje możliwośd nadania własnej nazwy plikowi wykonywalnemu,
- -lm wykorzystywana jest gdy korzystamy z biblioteki matematycznej (funkcje sinus, cosinus,
pierwiastek).
" Linker (konsolidator) tworzy plik wykonywalny. Dodaje kod biblioteki i kod startowy.
Kod startowy powoduje że program skompilowany pod jakimś systemem nie odpali się na innym.
Pobiera z bibliotek tylko te fragmenty, które wymagane są przez funkcje użyte w programie.
" Pliki wykonywalne:
- Windows: exe, com, bat
- Linux: out, nazwa, eXe TxT
" Atrybut wykonywalności:
nazwa.txt - rwxrwxrwx 0777
nazwa.exe
" Linux - podstawowe polecenia:
- ./a.out
- a.out
- a.out&
" Wymuszone zakooczenie działania aplikacji:
- Windows: CTRL + ALT + DEL, CTRL+SHIFT+ESC
- Linux: ps, kill PID, kill -9 PID, CTRL-Z, jobs, fg, bg
" Fajny debugger pod Linuxem: gdb
Wykład # Strona 2
-2-
PODSTAWOWE TYPY DANYCH
" Wyrażenia buduje się z elementów składowych:
- dane:
a) stałe
b) zmienne
- operatory
" W C89 zdefiniowanych jest 5 podstawowych typów danych:
1) brak wartości: void
2) znak: char
3) liczba całkowita: int
4) liczba zmiennoprzecinkowa: float
5) liczba zmiennoprzecinkowa podwójnej precyzji: double
" W pliku limits.h są wszystkie informacje na temat długości zmiennych np.
printf("CHAR_BIT = %d\n",CHAR_BIT);
Informacje są też w float.h - Linux 64bit
" Identyfikator - nazwa zmiennej, funkcji, etykiety
" Identyfikatory wewnętrzne są nieużywane w procesie konsolidacji, np. nazwy zmiennych
lokalnych.
" Liczba znaczących znaków:
- W C89 znaczących jest co najmniej 6 pierwszych znaków
- W C99: 31
- W C++: 1024 pierwszych znaków
" W standardzie C89 należy deklarowad zmienne lokalne na początku bloku, w którym są
definiowane, przed wszelkimi innymi instrukcjami. Ponadto nie można mieszad deklaracji z
przypisaniami.
Czyli np. takie coś w C89 jest błędne:
int i;
i = 10;
int j;
W C89 powinno byd:
int i;
int j;
i = 10;
" Nie zainicjalizowane zmienne statyczne i globalne mają wartośd 0, a lokalne - niewiadomo: śmieci.
" Zastosowanie w C notacji HEX:
- adresowanie pamięci:
- maski bitowe (chociaż raczej się je pisze w bin)
\f (feed) nowa strona
Dany jest fragment programu:
int n = 10, p = 9, q;
q = (n | p) + (n & p);
q = n |p + n || p;
q = n ==p;
q = --n + (p++ > 2);
q = (n < p) + n << 2;
q = --n > p++ ? n % p : p % n;
Wykład # Strona 3
Wykład #3
17 marca 2010
15:25
OPERATORY
" Rodzaje operatorów:
1) Arytmetyczne
2) Relacyjne
3) Logiczne
4) Bitowe
" Operatory są posegregowane w/g priorytetów (na górze najwyższy priorytet).
Przykład:
!0 && 0 || 0 //wartośd= 0
!(0 && 0) || 0 // wartośd1
" Istnieją 2 definicje dzielenia modulo jeśli chodzi o liczby ujemne. C ma inna od Python'a
funkcja fmod() // dzielenie modulo liczb innych niż całkowite
Przykład:
x = 10;
y = ++x; // najpierw odczytujemy x, zwiększamy o 1 i przypisujemy do y
wartośd zmiennej y wynosi 11
Przykład:
x = 10;
y = x++; // najpierw odczytujemy x, przypisujemy do y a potem zwiększamy o 1.
wartośd zmiennej y = 10.
Efekt uboczny: w obydwu przypadkach wartośd zmiennej x wynosi 11.
" W C nie ma bool
Wykład # Strona 4
Wykład #4
24 marca 2010
15:01
INSTRUKCJE
" Instrukcja to podstawowy element składowy programu. Program to skooczony ciąg instrukcji.
Instrukcja określa akcję, działanie.
Instrukcja to każde poprawne wyrażenie języka C zakooczone średnikiem.
" Z każdym wyrażeniem w języku C związana jest wartośd.
Przykład:
6 + (c = 3 + 8) //wartośd 17
Jest to istotne dlatego, bo nie ma typu logicznego w C, nie ma takich typowych tablic, ma to
znaczenie przy przekazywaniu argumentów do funkcji. W Javie nie każde wyrażenie ma wartośd.
// włg Gawrooskiego Java jest najbardziej podobna do C spośród języków z którymi się spotkamy
na studiach.
" Instrukcje w C dzielimy na następujące kategorie:
a) wyboru (warunkowe): if, switch
b) iteracyjne: while, for, do-while
c) skoku: break, continue, goto, return
d) etykiety: case, default
e) wyrażenia,
f) blokowe: {}
Maksymalne dopuszczalne zagnieżdżenie: 15 poziomów (C89), 127(C99)
SWITCH
- W instrukcji switch(wyrażenie)
case etykieta-stała: sekwencja instrukcji
break;
...
"etykieta-stała" po case musi byd stałą, tzn. kompilator musi ją znad w momencie kompilacji. Nie
możemy tam dad zmiennej z przydomkiem const.
- Standard C89(C99) określa, że w instrukcji switch może wystąpid co najwyżej 257 (1023) instrukcji
case.
- Instrukcja switch może jedynie sprawdzad równośd, inaczej niż instrukcja if, która może sprawdzad
dowolny typ wyrażenia logicznego, bądz relacyjnego.
- W switchu nie może wystąpid 2 razy ta sama wartośd.
- Stałe znakowe automatycznie przekształcane są do wartości typu całkowitego.
- Instrukcje break nie musza występowad wewnątrz instrukcji switch
- Instrukcje switch można zagnieżdżad.
W standardzie C99 dodali w stosunku do C89 możliwośd definiowania zmiennych w pętli for, w C
nie ma wyjątków.
EXIT():
- Funkcja exit() powoduje natychmiastowe zakooczenie całego programu i powrót do systemu
operacyjnego.
- Ogólna postad funkcji exit() zdefiniowanej w stdlib.h:
void exit(int kod powrotu);
wartośd kod powrotu przekazywana jest do procesu wywołującego. Na ogół 0 oznacza normalne
zakooczenie programu. Inne argumenty oznaczają błędy. Dostępne są makra: EXIT_SUCCESS oraz
EXIT_FAILURE
Wykład # Strona 5
-2-
TABLICE
" Tak naprawdę nie ma tablic w języku C. To znaczy jest funkcjonalnośd tablic, ciągłośd pamięci, ale
chodzi o to, że (i tutaj teraz moje tłumaczenie) jak zakładamy sobie tablicę, to tak naprawdę
kompilator rezerwuje nam miejsce w pamięci (przez moment wie, jak duża będzie ta tablica), my
dostajemy adres pierwszego elementu. Kompilator nie "ryje" w pamięci komórek na elementy
tablicy, nie wie nawet gdzie tablica się skooczy.
" Dzięki temu, że w C tablice* są oparte na wskaznikach są szybkie.
*ich tak naprawdę nie ma.
//Fajne tablice są w Ruby, Javie.
Wykład # Strona 6
Wykład #5
31 marca 2010
14:29
FUNKCJE, AAOCUCHY ZNAKOWE
" Funkcje z biblioteki standardowej operujące na łaocuchach znaków:
- strcpy(s1,s2) // kopiuje s2 do s1,
- strncpy(s1,s2,n) // kopiuje n znaków z s2 do s1,
- strcat(s1,s2) //dołącza s2 do kooca s1,
- strcat(s1,s2,n) // dołącza n znaków z kooca s2 do kooca s1,
- strcmp(s1,s2) // zwraca 0, jeśli s1 oraz s2 są identyczne, wartośd ujemną gdy s1s1>s2,
- strncmp(s1,s2,n) //porównuje do n znaków z s2 do s1,
- strlen(s1) // zwraca długośd s1,
- strchr(s1,ch) //zwraca wskaznik do pierwszego wystąpienia ch w s1,
- strstr(s1,s2) //zwraca wskaznik do pierwszego wystąpienia s2 w s1.
Programowanie proceduralne != programowanie funkcyjne.
" Normalnie funkcja nie może zwracad tablic, dlatego że czegoś takiego jak tablica nie ma ;-)
" W C89 można nie deklarowad typu zwracanego (ale nie zaleca się). W C99 już trzeba deklarowad
typ zwracany.
W C++ jak na liście parametrów formalnych nie ma nic, to jest void, w C natomiast jeśli jest taka
sytuacja to to znaczy że lista argumentów jest nieokreślona.
" Funkcje rekurencyjne przeważnie działają wolniej niż iteracyjne (patrz wykład z algorytmów).
W algorytmie rekurencyjnym jest dużo wywołao funkcji, wykonuje się dużo operacji wewnątrz
pamięci.
Bardzo głęboka rekurencja może spowodowad przepełnienie stosu.
Indeks pętli jest zmienną rejestrową.
Wykład # Strona 7
Wykład #6
14 kwietnia 2010
14:05
PRZEKAZYWANIE ARGUMENTÓW DO FUNKCJI.
" W różnych językach programowania argumenty do funkcji mogą byd przekazywane:
- przez wartośd
- przez referencję
Argumenty przekazane przez wartośd są kopiowane do parametrów formalnych. Zmiany wartości
parametrów formalnych nie mają wpływu na wartości argumentów.
W przypadku przekazania przez referencję, adres argumentu jest kopiowany do parametru.
Wewnątrz funkcji odwołanie do faktycznej wartości realizowane jest za pomocą adresu.
Z nielicznymi wyjątkami, w języku C argumenty przekazywane są przez wartośd.
Przykład:
int sq(int);
int main(void)
{
int t = 10;
printf("%d * %d = %d\n",t,t,sq(t));
return 0;
}
int sq(int t)
{
t *= t;
return t;
}
Tak naprawdę programowanie w C to operacje na pamięci.
" W C możemy symulowad przekazywane przez referencję, przekazując wskaznik do zmiennej,
zamiast samej zmiennej.
WSKAyNIKI
" Korzyści płynące ze wskazników:
- wskazniki to jedyny sposób, w który funkcje mogą modyfikowad swoje argumenty,
- wskazniki są podstawą dynamicznej alokacji pamięci,
- wskazniki pozwalają poprawid efektywnośd działania wielu procedur,
- wskazniki umożliwiają realizację dynamicznych struktur danych: listy, drzewa, itp.
" Wskaznik to zmienna przechowująca adres pamięci. Adres to lokalizacja innego obiektu (innej
zmiennej) w pamięci.
" Ogólna postad deklaracji wskaznika: typ *nazwa;
Typ podstawowy wskaznika określa, na jakiego typu zmienne może on wskazywad. Wszelkie
obliczenia na wskaznikach wykonuje się z uwzględnieniem typu podstawowego.
" W przypadku deklaracji int*, kompilator zakłada, że dowolny adres wskazywany przez niego
zawiera liczbę całkowitą, niezależnie od tego, co aktualnie zawiera wskazywany fragment pamięci.
- Programista musi zagwarantowad, że typ wskaznika jest zgodny z typem obiektu, na który on
wskazuje.
" Wskaznikowi, który nie zawiera poprawnego adresu należy nadad wartośd NULL (zero).
" Język C gwarantuje, że pod zerowym adresem nie istnieje żaden obiekt. Wskaznik o wartości NULL
nie wskazuje na żadną zmienną.
Wykład # Strona 8
-2-
Przykład:
int *pi;
float *pf, fl;
pi = NULL;
pf = &fl;
*pi = 81; // Błędna instrukcja, bo adres NULL nie może przechowywad żadnej innej wartości.
*pf = 12.89;
Zmienna która przechowuje adres, ma swój adres, który nie ma nic wspólnego z adresem który
przechowuje.
" Operatory powiązane ze wskaznikami:
- Operator & zwraca adres w pamięci dla operandu,
- operator * zwraca wartośd zmiennej, która znajduje się pod adresem operandu.
" Każda lokalizacja w pamięci jest identyfikowana przez unikalny adres.
" Każda lokalizacja w pamięci zawiera wartośd.
Przykład:
int i, *pi, *pj;
i = 9;
pi = &i;
pj = pi;
*pj = 123;
" Chcąc wypisad adres w printf() podajemy formatowanie: %p.
" Wskaznik typu void
- Wskaznik typu void * to wskaznik ogólny.
- Wskaznik typu void * można przypisad dowolnemu innemu wskaznikowi.
- Wskaznikowi typu void * można przypisad dowolny inny wskaznik.
- void * pozwala zdefiniowad parametr funkcji, która może przyjąd jako argument wskaznik
dowolnego typu.
- void * umożliwia określenie pamięci (np. malloc), gdy przeznaczenie takiej pamięci nie jest jeszcze
znane.
" Pomiędzy wskaznikami i tablicami istnieje ścisłe powiązanie:
Nazwa tablicy bez indeksu to wskaznik do pierwszego elementu.
Przykład:
int tab[10];
int *p;
p=tab;
Aby odwoład się do elementu o indeksie 4 w tablicy tab można skorzystad z: tab[4] lub *(p+4).
tab*4+ = 18 jest równoważna *(p+4)=18, jak również *(tab+4)=18 oraz p*4+ = 18.
" Na wskaznikach można wykonywad tylko dwie operacje arytmetyczne: dodawanie i odejmowanie.
Przykład:
int *pt, *ptf;
int tab[10] = {1};
pt = tab;
*(pt+3) = *pt + 3; // przypisanie, to nie jest sobie równe (==)
ptf = pt + 5; /* ustawienie wskaznika ptf na adres pokazywany przez wskaznik przesunięty o 5
pozycji dalej (5*sizeof(int)).*/
*(pt + 4) = *(ptf-2); // to samo co pt[4] = ptf[-2]
Wykład # Strona 9
-3-
TYPOWE BADY:
int main(void)
{
int x,*p;
x = 10;
p = x; //błędne przypisanie powinno byd p = &x;
printf("%d",*p);
return 0;
}
Przypisanie nadaje wskaznikowi wartośd 10. Zmienna p powinna zawierad adres, a nie wartośd.
" W systemie UNIX błąd segmentation fault (sygnał SIGSEGV) wskazuje, że wystąpiła próba dostępu
do adresu spoza pamięci przydzielonej dla programu.
Przykład:
int *ptr = NULL; // to samo co int *ptr; ptr = NULL;
*ptr = 1; //próbujemy wpisad coś po zerowy adres - błąd.
char *pointer;
pointer[10] = 'a';
//error: assignment of read-only location '*s'
const char *s = "hello world";
*s = 'H'; //również błąd, bo s miał byd wskaznikiem do stałej znakowej, a stałej nie można zmieniad
" Co inkrementuje *ptr++ ?
- Operatory * i ++ mają łącznośd prawostronną
- Konstrukcja *ptr++ inkrementuje ptr (i zwraca wartośd wskazywaną przez PIERWOTN wartośd
wskaznika).
- Aby zwiększyd o jeden obiekt wskazywany przez ptr, należy użyd (*ptr)++.
" Na wskaznikach typu void * nie można wykonywad operacji arytmetycznych.
" Błędny wskaznik trudno znalezd, gdyż wskaznik sam w sobie nie jest problemem.
Problem bierze się stąd, że używając niepoprawnego wskaznika, zapisujemy lub odczytujemy dane
z nieznanego obszaru pamięci. Odczytując dane, dostajemy śmieci. Zapisując dane, możemy
zamazad kod programu lub dane.
Wykład # Strona 10
Wykład #7
21 kwietnia 2010
14:18
W C możemy symulowad przekazywanie przez referencję, przekazując wskaznik do zmiennej,
zamiast samej zmiennej.
W C nie można przekazad do funkcji całej tablicy. Do funkcji można przekazad tylko i wyłącznie
adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu.
Przykład:
int main(void)
{
int tab[10];
func(tab);
return 0;
}
3 sposoby deklaracji funkcji func():
1) void func(int *x);
2) void func(int x[10]);
3) void func(int x[]);
One niczym się nie różnią.
sizeof (x) zwraca rozmiar wskaznika, nie tablicy.
TABLICE - UZUPEAENIENIE
" Dla tablic przewidziano tylko 2 operacje:
- określenie rozmiaru tablicy,
- uzyskanie wskaznika pierwszego elementu tablicy (o indeksie zerowym).
Wszystkie pozostałe operacje są w istocie realizowane na wskaznikach, nawet jeśli zapis sugeruje
co innego, np. a[i].
" W C nazwa a odnosi się do adresu elementu tablicy a*+ o indeksie zero w każdym kontekście, z
wyjątkiem jednego, kiedy to występuje jako argument operatora sizeof.
" Zapis sizeof(a) - reprezentuje rozmiar całej tablicy, a nie rozmiar wskaznika jednego z jej
elementów, chyba że w bloku kodu w którym tablica była stworzona, wtedy pokazuje adres całej
tablicy.
" Notacja
typ a[size];
*a = 18 - przypisujemy wartośd elementowi o indeksie 0
*(a+5) = 18 - przypisujemy wartośd elementowi o indeksie 5.
*(5+a) = 18 - to samo
a[5] = 18 - to samo
5[a] = 18 - to samo, zadziała, ale nie zaleca się takich operacji robid
W C nie ma w istocie tablic wielowymiarowych.
" Element tablicy może byd obiektem dowolnego typu, również inną tablicą - umożliwia to
symulowanie tablic wielowymiarowych.
Przykład:
int tab[3][4];
tab[1][2] = 7;
tab[i][j] = i*4+j+1;
// i - wiersze, j - kolumny
Wykład # Strona 11
-2-
" Rozmiar tablicy dwuwymiarowej w bajtach = rozmiar 1-go indeksu x rozmiar 2-go indexu x
sizeof(typ podstawowy).
" Ogólna postad inicjalizacji tablicy:
typ nazwa_tablicy[rozmiar1] = {lista wartosci};
" Aby utworzyd tablicę łaocuchów (stringów) tworzymy dwuwymiarową tablicę znaków. Rozmiar
lewego indeksu określa liczbę łaocuchów, natomiast rozmiar prawego indeksu określa
maksymalną liczbę znaków w każdym łaocuchu.
Przykład: tablica 30 łaocuchów o max. długości 79 znaków.
char str_array[30][80];
int a1 = strlen(str_array[2]); //oblicza długośd 3 łaocucha.
int a2 = strlen(&str_array[2][0]); //oblicza długośd 3 łaocucha. Rzadko się stosuję tą notację.
" Dla dowolnej tablicy dwuwymiarowej a*j+*k+ jest równoważne *(*a + (j * długośd wiersza) + k)
Przykład:
int a[10][10];
a[1][2] = 32;
*(*a+12) = 32;
*(*(a+1)+2) = 32;
Tablice to nie wskazniki chod są blisko z nimi związane.
- char a*+ i char *p to to samo tylko w przypadku parametrów formalnych funkcji.
Deklaracji char a*6+ przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą a.
Deklaracja char *p przydziela miejsce na 1 wskaznik. Wskaznik może wskazywad:
1) na pojedyncza zmienną typu char,
2) na ciągłą tablicę typu char,
3) nigdzie - wskaznik pusty.
Przykład:
char a[] = "hello";
char *p = "world";
Jak przetłumaczyd x*3+?
- a[3] - wez adres tablicy a dodaj do niego 3 i pobierz znak,
- p[3] - wez adres wskaznika p, pobierz jego wartośd, dodaj do niej 3 i pobierz znak.
Gdzie znajduje się x*3+???
- a[3] - znak odległy o 3 miejsca od początku obiektu o nazwie a.
- p[3] - znak odległy o 3 miejsca od obiektu wskazywanego przez p.
" Wskazniki można umieszczad w tablicach tak jak inne typy danych.
Ogólna postad deklaracji tablicy wskazników:
typ*nazwa[romiar]
" Tablic wskazników używa się np. do przechowywania łaocuchów.
" int main(int argc, char *argv[]) i int main(int argc, char **argv) oznaczają to samo.
argc typu int , to liczba argumentów wiersza poleceo, >= 1.
Parametr argv to wskaznik do tablicy wskazników znakowych. Każdy element tej tablicy wskazuje
na argument wiersza poleceo. Wszystkie argumenty wiersza poleceo to łaocuchy.
" Wskaznik może wskazywad na inny wskaznik, który z kolei wskazuje na docelową wartośd.
W przypadku wskaznika do wskaznika pierwszy wskaznik zawiera adres drugiego, który z kolei
wskazuje na obiekt zawierający właściwą wartośd. Ogólna postad deklaracji wskaznika do
wskaznika: typ **nazwa;
Wykład # Strona 12
-3-
Przykład:
float x, *p, **q;
x = 10.01;
p = &x;
q = &p;
printf("x = %f\n", **q);
" Funkcja ma w pamięci swoją lokalizację, którą można przypisad wskaznikowi.
- Ten adres to punkt początkowy funkcji, używany przy jej wywołaniu.
- Gdy wskaznik wskazuje na funkcję, można ją wywoład za jego pośrednictwem.
- Wskazniki do funkcji pozwalają przekazywad funkcje jako argumenty do innych funkcji.
- Adres funkcji uzyskuje się podając jej nazwę bez nawiasów i argumentów.
cdecl - program który jest w stanie przeczytad tekst angielski na deklaracje w języku c i odwrotnie.
cdecl jest na fatcacie i ogólnie we wszystkich dystrybucjach Linux (podobno).
przykład użycia:
explain int tab[]
Wykład # Strona 13
Wykład #8
28 kwietnia 2010
14:01
KWALIFIKATORY TYPU
" W standardzie C89 zdefiniowane zostały dwa kwalifikatory typu, charakteryzujące stałośd (const)
oraz ulotnośd (volatile) zmiennej. Kwalifikator musi poprzedzad nazwę typu, którego dotyczy.
// włg Hawk'a const powinno się nazywad read-only.
" const
- zmiennych typu const program nie może zmodyfikowad
- zmiennym typu const można nadad wartośd początkową
- const float pi = 3,14;
" volatile
- Modyfikator volatile informuje kompilator, że wartośd zmiennej może się zmienid w sposób
niezależny od programu. Wartośd zmiennej modyfikowana jest bez jakiegokolwiek przypisania jej
wartości w programie.
- Zwykle jest on wykorzystywany w odniesieniu do adresów sprzętowych lub danych
współdzielonych z innymi, działającymi równolegle programami.
KWALIFIKATOR CONST:
" Kwalifikator const może odnosid się również do wskaznika lub do wskazywanej przezeo wartości.
Przykład:
const int *ptr; // ptr wskazuje na stałą wartośd typu int
- wartośd zmiennej wskaznikowej ptr może ulec zmianie.
- wartośd zmiennej *ptr musi pozostad stała.
Przykład:
int *const pts = &a; // pts jest stałym wskaznikiem
- pts ma stałą wartośd, musi wskazywad zawsze na to samo miejsce w pamięci,
- wartośd zmiennej *pts może ulec zmianie.
Przykład:
const int * const ptt;
- ptt wskazuje zawsze na to samo miejsce w pamięci, a znajdująca się w tym miejscu wartośd nie
może zostad zmieniona.
" Kwalifikator const jest często wykorzystywany do deklarowania wskazników będących formalnymi
parametrami funkcji: void fun(const int *tab);
" Dane wskazywane przez parametr tab nie mogą ulec zmianie. Dobry sposób na ochronę danych
przed przypadkową zmianą wartości.
" Kwalifikator const jest używany często w funkcjach z biblioteki standardowej C.
np. char *strcat(char*, const char *);
Kwalifikatory const i volatile nie wykluczają się nawzajem.
Zegar sprzętowy komputera nie powinien byd modyfikowany przez program (const), ale
równocześnie jest modyfikowany przez czynniki inne niż program (volatile).
const volatile char * port = (const volatile char *) 0x30.
SPECYFIKATORY KLASY PAMICI
W języku C występują 4 modyfikatory określające klasę przechowywania:
- extern
- static
- register
- auto
Wykład # Strona 14
-2-
" Modyfikatory te informują kompilator jak przechowywad przyszłe wartości
klasa_przechowywana typ nazwa_zmiennej;
" Standardy C89 i C99 ze względu na wygodę składniową określają że typedef to specyfikator klasy.
W powszechnym rozumieniu tego pojęcia typedef nie jest specyfikatorem klasy.
" Z punktu widzenia procesu konsolidacji istnieją 3 kategorie nazw:
- zewnętrzne - nazwy funkcji i zmiennych globalnych- dostępne dla wszystkich plików, z których
składa się program,
- wewnętrzne - obiekty o zasięgu pliku zadeklarowane jako static - znane jedynie w pliku, w którym
znajduje się ich deklaracja,
- żadne - zmienne lokalne, znane jedynie we własnym bloku.
" Podstawowe zastosowanie słowa kluczowego extern to określenie, że obiekt o zewnętrznej
kategorii konsolidacji jest zdeklarowany w innej części programu.
" Definicja vs deklaracja
- Deklaracja deklaruje nazwę i typ obiektu
- Definicja przydziela miejsce w pamięci obiektowi
- Ten sam obiekt może mied kilka deklaracji i tylko jedną definicję
- często deklaracje są jednocześnie definicjami.
" extern - używamy aby zadeklarowad zmienną zdefiniowaną w innej części programu, np. w innym
pliku zródłowym.
Jeżeli program składa się z kilku plików dobrym sposobem na przekazanie do wszystkich plików
informacji o zmiennych globalnych jest zadeklarowanie wszystkich zmiennych globalnych w
jednym pliku i użycie deklaracji extern w pozostałych.
" Modyfikator extern informuje kompilator, że zmienne o podanych typach i nazwach mają swoje
definicje gdzie indziej i nie trzeba dla nich tworzyd miejsca w pamięci.
" Podczas konsolidacji linker rozwiązuje odwołania do zmiennych typu extern
" Zmienne statyczne (static) to trwałe zmienne znajdujące się wewnątrz pliku bądz funkcji.
" Wartości zmiennych statycznych nie znikają pomiędzy wywołaniami funkcji.
" Modyfikator static ma różny wpływ na zmienne lokalne i globalne.
" Statyczne zmienne lokalne:
- Gdy zmiennej lokalnej zostanie przypisany modyfikator static, to kompilator utworzy dla niej stałe
miejsce w pamięci, analogicznie jak dla zmiennej globalnej.
- Lokalna zmienna statyczna widoczna jest tylko w tym bloku gdzie została zdefiniowana.
- Lokalna zmienna statyczna to zmienna lokalna, która zachowuje swoją wartośd pomiędzy
wywołaniami funkcji.
" Statyczne zmienne globalne:
- Przypisanie zmiennej lokalnej modyfikatora static informuje kompilator, że należy utworzyd
zmienną globalną, znaną jedynie w pliku, w którym znajduje się jej deklaracja.
- Procedury z innych plików nie będą miały do niej dostępu.
" Zmienne rejestrowe.
- Modyfikator register początkowo odnosił się jedynie do zmiennych typu int, char oraz do
wskazników. Obecnie można go stosowad do zmiennych dowolnego typu.
- Stosuje się go do zmiennych lokalnych i parametrów formalnych.
- Standardy C89 i C99 określają, że zmienna rejestrowana ma zapewnid najszybszy możliwy dostęp
do jej wartości.
- W praktyce zmienne typu int oraz char są umieszczane w rejestrach procesora.
- Większośd obiektów takich jak tablice nie można umieścid w rejestrze, ale można im zapewnid
uprzywilejowane traktowanie przez kompilator.
- W zależności od kompilatora oraz systemu operacyjnego, zmienne rejestrowe mogą byd
traktowane różnie
- Dopuszczalne jest również zignorowanie modyfikatora, ale w praktyce rzadko się to zdarza.
- Zmienne rejestrowe są optymalizowane pod kątem szybkości działania i stosowane są tam gdzie
ma miejsce wiele odwołao do tej samej zmiennej, np. pętle.
- Gdy przekroczona zostanie dopuszczalna liczba zmiennych rejestrowych to kompilator
automatycznie zamienia je na zwykłe zmienne.
Wykład # Strona 15
-3-
- Zazwyczaj 2 zmienne typu int oraz char da się umieścid w rejestrach procesora.
- Nie można określid adresu zmiennej rejestrowej za pomocą operatora &, ponieważ nie można
określid adresu rejestru procesora.
DYNAMICZNA ALOKACJA PAMICI
FUNKCJE DYNAMICZNEJ ALOKACJI PAMICI
" Wskazniki pozwalają realizowad dynamiczną alokację pamięci.
" Dynamiczna alokacja pamięci to sposób, w jaki działający program uzyskuje dodatkową pamięd,
której ilości nie można określid przed jego uruchomieniem.
" Dynamiczna alokacja pamięci umożliwia tworzenie dynamicznych struktur danych.
" Funkcje dynamicznej alokacji pamięci przydzielają pamięd ze sterty. Sterta to wolna pamięd,
nieużywana przez żaden program ani przez system operacyjny.
" Rozmiar sterty z reguły jest dośd duży, jednak ograniczony i pamięd ze sterty może się wyczerpad.
" Funkcje dynamicznej alokacji pamięci zdefiniowane w nagłówku stdlib.h to:
- void *malloc (size_t liczbabajtów);
- void *calloc (size_t num, size_t liczbabajtów);
- void *realloc (void * blokpamieci, size_t liczbabajtów);
- void free (void * blokpamięci);
malloc() od calloc() różni się tym, że calloc poza nieco innymi parametrami formalnymi, zeruje
zarezerwowany obszar.
W C++ istnieje coś takiego jak new, co jest podobne do malloc'a. Niestety w C++ nie ma nic co
odpowiada realloc'owi. Oczywiście można w C++ korzystad z realloc'a.
Przykład:
char *p;
p = (char *) malloc(100);
// alokacja 100 bajtów ciągłej pamięci, p wskazuje na pierwszy bajt.
Przykład:
int *p;
p = (int *) malloc (50 * sizeof(int));
if (!p)
{
printf("Brak pamieci\n");
exit(-1);
}
free(p);
Dwiczenie: jak przy pomocy malloc() stworzyd sobie tablicę dwuwymiarową?
Wykład # Strona 16
Wykład #9
5 maja 2010
LISTA PARAMETRÓW O ZMIENNEJ DAUGOŚCI
" Każda funkcja o zmiennej długości parametrów musi mied co najmniej 1 parametr formalny.
" Makra zdefiniowane w umożliwiają przekazanie do funkcji listy argumentów o
zmiennej długości:
- typ va_argh(va_list argptr, typ)
- void va_copy(va_list trgt, va_list src)
- void va_start(va_list argptr, last_param)
- void va_end(va_list argptr)
" Korzystanie z funkcji o zmiennej ilości argumentów:
- inicjalizujemy wskaznik do argumentów argptr, wywołując makro va_start()
- pozostałe parametry uzyskuje się wywołując makra va_arg( )
STRUKTURY, UNIE, WYLICZENIA, TYPEDEF
" W C jak deklarujemy strukturę, to w przeciwieostwie do C++ trzeba użyd słowa struct, np.:
struct nazwa_struktury nazwa_zmiennej;
" Nie można w C strukturze o nazwie a i liście parametrów przypisad wartośd struktury o nazwie b i
takiej samej liście argumentów.
WSKAyNIKI DO STRUKTUR
" struct etykieta * nazwa_zmiennej; // deklaracja wskaznika do struktury
Wykład # Strona 17
Wykład #10
12 maja 2010
POLA BITOWE
" Język C pozwala odwoływad się konkretnych bitów za pośrednictwem pól bitowych.
" Pola bitowe umożliwiają, np. w przypadku ograniczenia pamięci, w jednym bajcie przechowad
kilka zmiennych logicznych.
" Pole bitowe musi byd składową struktury lub unii.
" Pola bitowe to specjalny typ składowych, określające długośd (w bitach) pola.
" Ogólna postad definicji pola bitowego:
- typ nazwa : długośd;
- typ to int, signed, unsigned.
- długośd to liczba bitów
" Z pól bitowych często korzysta się przy analizowaniu danych pochodzących z urządzeo
zewnętrznych. Port statusu karty szeregowej - 1 bajt
struct status type
{
unsigned delta_cts :1;
unsigned delta_dsr :1;
unsigned tr_edge :1;
unsigned delta_rec :1;
unsigned cts :1;
unsigned dsr :1;
unsigned ring :1;
unsigned rec_line :1;
} status;
status = get_port_status();
if (status.cts) printf("clear to send");
if (status.dsr) printf("data ready");
status.ring = 0;
Przykład - można pominąd nieużywane bity
struct status_type
{
unsigned : 4;
unsigned cts :1; // interesują nas tylko bity 5 i 6, pomijamy nieużywane
unsigned dsr :1;
} status;
" Można jednocześnie umieszczad w strukturze zwykłe elementy oraz pola bitowe.
" Nie można pobrad adresu pola bitowego.
" Nie można tworzyd tablic pól bitowych.
" Pól bitowych nie można deklarowad jako statycznych.
" Korzystanie z pól bitowych wiąże kod z konkretnym typem komputera; nie wiadomo czy pola
bitowe układają się od lewej do prawej czy też odwrotnie. (Informacja nie dostępna dla żadnego
typu)
" Kod operujący na polach bitowych jest zazwyczaj dużo jaśniejszy niż odpowiadające źjawen
operacje na maskach bitowych.
" Wyliczenie to zbiór stałych całkowitych o określonych nazwach.
" Ogólna postad wyliczenia:
- enum etykieta {lista wartości} lista-zmiennych;
Wykład # Strona 18
-2-
Przykład:
enum moneta {penny, nickel, dime, quarter, half_dolar, dolar};
enum moneta pieniadz;
...
pieniadz = dime;
...
if (pieniadz == quarter) ...
" Każdy symbol wyliczenia reprezentuje stałą całkowitą.
" Wyliczeo można używad tam gdzie można użyd liczby całkowitej.
" Każdy symbol otrzymuje wartośd o jeden większą od wartości poprzedniego symbolu. Wartośd
pierwszego symbolu to zero.
" Można również określid wartości jednego lub kilku symboli.
Przykład:
enum moneta {penny, nickel, dime, quarter = 100, half_dolar, dolar);
" Używając słowa kluczowego typedef można zdefiniowad nowe nazwy typów.
" typedef nie służy do tworzenia nowych typów.
" Ogólna postad instrukcji
- typedef typ nowa_nazwa_typu;
Przykład:
typedef float saldo;
saldo wrzesien;
typedef struct telement
{
int wiek;
struct telement *nast;
} element;
element *root; // struct telement *root;
PREPROCESOR
" Preprocesor pozwala na:
- definiowanie makrodefinicji, które upraszczają postad kodu zródłowego i zwiększają jego
czytelnośd.
- włączanie tekstów innych plików; np. zbiory nagłówkowe zawierające prototypy standardowych
funkcji bibliotecznych, definicje niezbędnych stałych itp..
- sterowanie przebiegiem kompilacji
" Dyrektywy preprocesora:
#define, #elif, #else, #if, #ifdef, #ifndef, #include, #line, #pragma, #undef.
" Dyrektywa #pragma to dyrektywa zależna od implementacji, pozwalająca przekazywad
kompilatorowi różne instrukcje.
" Dyrektywa #define definiuje identyfikator i ciąg znaków, które zostaną podstawione w każdym
miejscu wystąpienia identyfikatora w pliku zródłowym.
" Ogólna postad dyrektywy:
- #define nazwa-makra ciąg-znaków
Przykład:
#define TRUE 1
#define FALSE 0
#define MAX_TAB 1234
#define ERR_MSG "Błąd odczytu. \n"
Wykład # Strona 19
-3-
int tab[MAX_TAB];
printf("ERR_MSG");
" Dyrektywa #define może przyjmowad argumenty.
" Ogólna postad dyrektywy z parametrami:
- #define nazwa-makra(PAR1, PAR2, ...) ciąg znaków
Przykład:
#define ILORAZ(a,b) ((a)/(b))
#define ABS(a) (a) < 0 ? -(a):(a)
" Nawiasy (a), (b) zapewniają poprawne podstawienie.
" Makra zwiększają prędkośd działania programu, kosztem rozmiaru kody wynikowego.
" Rozwijanie makrodefinicji jest operacją czysto tekstową.
" Reguły bezpieczeostwa:
- Ciało makrodefinicji musi byd zawsze ujęte w nawiasy, aby "ochronid", w otaczającym rozwiniecie
makrodefinicji wyrażeniu, operatory o niższym priorytecie.
- W ciele makrodefinicji wszystkie wystąpienia parametrów muszą zawsze byd ujęte w nawiasy, aby
"ochronid" operatory o niższym priorytecie, które mogą pojawid się w jej argumentach.
- Gdy parametr makrodefinicji występuje w jej ciele więcej niż raz, może ona działad niepoprawnie,
jeżeli obliczanie argumentu wywołuje efekty uboczne.
Przykład - definicja typu wskaznik struktury foo:
#define T1 struct foo *
typedef struct foo *T2
T1 a,b; //zostanie rozwinięte do struct foo *a, b;
T2 c,d;
" Preprocesor pozwala na "oddefiniowanie" zdefiniowanych wcześniej makr za pomocą dyrektywy
#undef
Przykład:
#define NAME "KINGA"
...
#undef NAME
...
#define NAME "KASIA"
...
" Dopuszczalne jest również przedefiniowanie makrodefinicji już zdefiniowanych bez konieczności
ich "oddefiniowania".
" Preprocesor ma dwa operatory: # oraz ##, używa się ich w powiązaniu z dyrektywą #define.
" Operator tworzenia łaocuchów #, zamienia poprzedzany argument na łaocuch, czyli ciąg otoczony
znakami cudzysłowu.
Przykład:
#define mkstr(s) #s
...
printf(mkstr(kilka słów));
" Operator sklejania łaocuchów ##, łączy dwa obiekty.
Przykład:
#define concat(a,b) a##b
...
int xy = 10;
printf("%d",concat(x,y));
Wykład # Strona 20
-4-
" Dyrektywa #error zmusza kompilator do przerwania kompilacji.
" Używa się jej głównie do debugowania programów.
" Ogólna postad dyrektywy:
- #error komunikat-błędu
" Po napotkaniu dyrektywy #error kompilator wyświetla komunikat błędu i ewentualnie inne
informacje zdefiniowane przez kompilator.
" Dyrektywa #include służy do dołączenia zawartości pliku do kodu zródłowego.
" Używa się jej głównie do włączania tzw. plików nagłówkowych.
" Ogólna postad dyrektywy:
- #include nazwapliku
Przykład
#include
#include "../moje_funkcje.h"
" Dyrektywy #if, #else, #elif, #endif pozwalają warunkowo dołączyd fragmenty kodu do kompilacji.
" Po dyrektywie #if wymagane jest wyrażenie stałe.
" Jeżeli w wyrażeniu tym występują identyfikatory zdefiniowane wcześniej przy pomocy dyrektywy
#define to są one zastępowane odpowiednimi napisami. Wyrażenia nie mogą byd zakooczone
średnikami.
" Ogólny schemat użycia dyrektyw kompilacji warunkowej:
#if wyrażenie-stałe
sekwencja instrukcji
#elif wyrażenie-stałe
sekwencja instrukcji
#elif wyrażenie-stałe2
sekwencja instrukcji
...
#elif wyrażenie-stałeN
sekwencja instrukcji
#endif
Przykład:
#define USA 0
#define ANGLIA 1
#define EUROLAND 2
#define AKTYWNY_KRAJ USA
#if AKTYWNY_KRAJ == USA
char waluta[] = "dolar"
#elif AKTYWNY_KRAJ == ANGLIA
char waluta[] = "funt"
#else
char waluta[] = "euro"
#endif
" Standard C89 (C99) określa, że dyrektywy #if, #ifdef, #ifndef oraz #elif można zagnieżdżad do co
najwyżej 8 (63) poziomów.
" Każda dyrektywa #endif, #else, oraz #elif wiąże się z najbliższą dyrektywą #if lub #elif.
" Dyrektywy #ifdef i #ifndef oznaczają "jeśli zdefiniowano" i "jeśli nie zdefiniowano".
" Ogólna postad dyrektywy #ifdef;
#ifdef nazwa-makra
sekwencja instrukcji
#endif
Wykład # Strona 21
-5-
" Jeśli nazwa-makra została uprzednio zdefiniowana za pomocą dyrektywy #define, wówczas ma
miejsce kompilacja kodu związanego z dyrektywą #ifdef.
Przykład:
#ifdef DEMO
/* kod tylko dla wersji demonstracyjnej */
#endif
#ifndef DEMO
/* kod tylko dla wersji normalnej */
#endif
" Dyrektywa #line zamienia zawartośd stałych __LINE__ oraz __FILE__, będących predefiniowanymi
identyfikatorami kompilatora.
" __LINE__ zawiera numer aktualnie kompilowanego wiersza.
" __FILE__ to łaocuch reprezentujący nazwę aktualnie kompilowanego pliku zródłowego.
" Ogólna postad dyrektywy #line:
#line numer "nazwapliku"
" numer to dowolna liczba całkowita, która staje się nową wartością __LINE__, nazwapliku staje się
nową wartością __FILE__.
Wykład # Strona 22
Wykład #11
19 maja 2010
14:03
#line
Przykład:
#include
#line 100 // ustaw licznik wierszy
int main (void)
{
//wiersz 100
printf("%d\n",__LINE__); //wiersz 101
return 0;
}
To nam może pomóc znalezd w którym momencie programu się on wywala.
Lepszym wyjściem jest użycie debuggera: gdb - potężne narzędzie.
" W języku C istnieje 5 predefiniowanych nazw makr:
- __LINE__, __FILE__
- __DATE__ to łaocuch w postaci miesiąc/dzieo/rok reprezentujący datę zamiany pliku zródłowego
na obiektowy.
- __TIME__ to łaocuch w postaci godzina/minuta/sekunda reprezentujący czas kompilacji pliku
zródłowego.
- __STDC__ ma wartośd 1, gdy kompilator jest zgodny ze standardem C.
LISTA, STOS, KOLEJKA, DRZEWO
Są to abstrakcyjne typy danych. Jeśli chcemy lepiej poznad abstrakcyjne typy danych dobrze
przeczytad książkę "Algorytmy w C".
LISTA JEDNOKIERUNKOWA
" typedef struct tnode
{
int value;
struct tnode *next;
} node;
node *tmp = (node *)malloc(sizeof(node));
if (!tmp)
{
printf("BAD alokacji\n");
exit(1);
}
" Dodawanie na początek:
1. Utwórz nowy element.
2. Uzupełnij pola danych nowego elementu.
3. Ustaw next nowego elementu na pierwsze element listy.
4. Zmieo head by wskazywał na nowy element listy.
Wykład # Strona 23
-2-
node *insert_item_begin (node * head, int val)
{
node *temp = (node*)malloc(sizeof(node));
if(!temp)
{
printf("Brak pamieci!!!!\n");
exit(1);
return head;
}
temp -> value = val;
temp -> next = NULL;
if (head)
temp - >next = head;
return temp;
}
" Dodaj nowy element do listy posortowanej
1. before wskazuje na element przed miejscem wstawienia.
2. after wskazuje na element za miejscem wstawienia.
3. Utwórz nowy element.
4. Uzupełnij pola danych nowego elementu.
5. Modyfikuj zawartośd before->next by wskazywał na nowy element
6. Modyfikuj zawartośd next nowego elementu by wskazywał na after.
Wykład # Strona 24
Wykład #12
26 maja 2010
14:02
STOS
STOS - IMPLEMENTACJA ZA POMOC LISTY:
node *push(node *top, int val);
node *instert_item_begin (node *top, int val);
int pop (node **top)
{
int x = (*top) -> value;
*top = (*top) -> next;
//tutaj można by zwolnid pamięd która była na wierzchu stosu np free(top)
return x;
}
// można by napisad funkcję multipop, która potrafiłaby ściągad n-elementów ze stosu.
// W książce "Algorytmy w C" jest lepiej zaimplementowany stos.
KOLEJKA
KOLEJKA-IMPLEMENTACJA ZA POMOC LISTY:
node * enqueue(node *top, int val);
node *insert_item_end(node *top, int val);
int dequeue(node ** head);
int pop(node **head);
" Musimy mied wskazniki na początek i na koniec kolejki, może ilośd elementów.
DRZEWA
#include
#define REL(a,b) (a)>(b)?(1):(0)
typedef struct tbstree
{
int key;
struct tbstree *left;
struct tbstree *right;
} bstree;
bstree *CreateLeaf(int a)
{
bstree *t = (bstree *)malloc(sizeof(bstree));
if (!t)
{
printf("brak pamieci");
exit(1);
}
t ->key = a;
t->left = t->right= NULL;
return t;
}
Wykład # Strona 25
-2-
void AddLeaf(int a, bstree **tr)
{
if (*tr)
{
if (REL((*tr)->key,a)) AddLeaf(a,&(*tr)->left);
else
AddLeaf(a,&(*tr)->right);
}
else
*tr = CreateLeaf(a);
}
void NodeOut( int level, bstree *nd)
{
int i;
for (i=1;iprintf(" ");
printf("Adres: %p, key: %d, left->%p, right->%p\n",nd,nd->key,nd->left,nd->right);
}
void DeleteTree(bstree *tr)
{
if (tr->left!=NULL)
DeleteTree(tr->left);
if (tr->right != NULL)
DeleteTree(tr->right);
free(tr);
}
void PrintTree(int level, bstree *tr)
{
if (tr)
{
NodeOut(level,tr);
PrintTree(level+1,tr->left);
PrintTree(level+1, tr->right);
}
}
#include "tree.h"
#define MAX 7
int main(int argc, char *argv[])
{
bstree *a = NULL;
int atab[MAX] = {15,5,20,9,25,1,19};
int i;
for(i=0;iAddLeaf(atab[i],&a);
PrintTree(1,a);
DeleteTree(a)
return 0;
}
Wykład # Strona 26
-3-
" Jednym z punktów egzaminu jest interface listy jednokierunkowej, drzewa (stosu/kolejki), raczej
listy dwukierunkowej nie będzie, bo nie było na wykładzie za dużo.
BIBLIOTEKA STANDARDOWA
" Standard ANSI/ISO C definiuje zarówno zawartośd, jak i postad standardowej biblioteki języka C.
" Standard określa zestaw funkcji, w które wszystkie kompilatory muszą byd wyposażone.
" Biblioteka to zbiór funkcji, linker dodaje do programu tylko te funkcje, z których program
faktycznie korzysta.
" Każda funkcja zdefiniowana w standardowej bibliotece ma odpowiadający jej nagłówek, który
dołączamy za pomocą dyrektywy #include.
" Wiele funkcji z biblioteki standardowej korzysta z własnych typów danych, definicje tych typów
znajdują się w plikach nagłówkowych związanych z daną funkcją.
Przykład:
#include
FILE *plik;
" Nagłówki przechowują prototypy standardowych funkcji bibliotecznych.
" Nagłówki zdefiniowane w C89:
- - definiuje makro assert() // diagnoza błędów w momencie uruchomienia
- - obsługa znaków
- - raportowanie błędów
- - definiuje zależne od implementacji limity zmiennoprzecinkowe
- - definiuje różne limity zależne od implementacji
- wspomaga lokalizacje programu
- - różne definicje wykorzystywane przez bibliotekę matematyczną
- - umożliwia "nie-lokalne" skoki // Przy pomocy instrukcji goto() możemy wyskoczyd z
jakiegoś miejsca, ale możemy wskoczyd w jakieś miejsce (do tego samego bloku kodu). setjmp
umożliwia wyskakiwanie z funkcji, wskakiwanie do innych.
- - wspomaga obsługę sygnałów
- - wspomaga obsługę zmiennych list argumentów
- - definiuje niektóre powszechnie używane stałe
- - wspomaga system wejścia/wyjścia
- - różne deklaracje
- - wspomaga funkcje obsługujące łaocuchy
- - wspomaga funkcje obsługujące czas systemowy.
" Nagłówki to z reguły pliki, ale wcale nie muszą byd plikami.
" Kompilator może zawierad wewnętrzną definicję nagłówka.
" W C89 funkcje matematyczne operują na zmiennych typu double
" Wszystkie wartości kątowe wyrażone są w radianach.
" W standardzie C99 zdefiniowano ponad 3x więcej funkcji.
" grcl ?
Wykład # Strona 27
Wykład #13
2 czerwca 2010
14:04
FUNKCJE WEJŚCIA/WYJŚCIA
" W nagłówku znajdują się definicje makr oraz typów używanych do operacji na plikach.
" Najważniejszy typ to FILE, za pomocą którego definiuje się wskazniki do plików.
" size_t(unsigned int) to typ zwracany przez operator sizeof.
" fpos_t definiuje obiekt, który może określad dowolną pozycję w pliku.
" Najczęściej używane makro to zdefiniowane w tym nagłówku to EOF (wartośd kooca pliku).
Jeżeli ktoś chciałby napisad program, który obsługuje sied to musi skorzystad z bibliotek nie
będących bibliotekami standardowymi.
" Plik - jednostka logiczna przechowywania danych w pamięci masowej.
" Plik - ciąg (zbiór) danych identyfikowany nazwą, o skooczonej długości, posiadający szereg
atrybutów i stanowiący dla systemu operacyjnego całośd.
" Plik binarny - plik zawierający dowolny ciąg danych zakodowany w systemie binarnym.
Bezpośrednio nieczytelny dla człowieka.
" Podstawowa jednostka danych to 1 bajt.
" Pliki binarne to wszystkie pliki poza plikami rejestrowymi.
" Plik tekstowy - plik zawierający tekst zapisany w ustalonym sposobie kodowania znaków
drukarskich (np. ASCII, Unicode) wraz z kodami sterującymi, w tym także kod znaku kooca pliku -
CTRL+Z
" Plik tekstowy to ciąg znaków z podziałem na wiersze.
" Podstawowa jednostka danych to jeden znak:
- jeden znak kodowany w ASCII to 1 bajt.
- Jeden znak w standardzie Unicode to dwa bajty lub więcej.
" Koniec linii w pliku tekstowym:
- Windows CR LF (\r \n) (0x0A 0x0D),
- Unix LF (\n) (0x0D),
- Macintosh CR (\r) (0x0A).
FILE * fopen(const char *fname, const char *mode);
" fopen - otwiera plik o nazwie fname i zwraca związany z nim strumieo. Typy dozwolonych operacji
na pliku określa wartośd parametru mode. Nazwa pliku musi byd łaocuchem.
" Dopuszczalne wartości parametru mode:
- "r" - otwarcie pliku tekstowego do odczytu,
- "w" - utworzenie pliku tekstowego do zapisu,
- "a" - otwarcie pliku tekstowego do dopisywania,
- "rb" - otwarcie pliku binarnego do odczytu,
- "wb" - utworzenie pliku binarnego do zapisu,
- "ab" - otwarcie pliku binarnego do dopisywania,
- "r+" - otwarcie pliku tekstowego do odczytu/zapisu
- "w+" - utworzenie pliku tekstowego do odczytu/zapisu,
- "a+" - otwarcie pliku tekstowego do odczytu/dopisywania.
- "rb+"
- "wb+"
- "ab+"
" Jeśli funkcji fopen() uda się otworzyd określony plik wówczas zwraca wskaznik do typu FILE> Jeśli
pliku nie można otworzyd zwraca wskaznik zerowy.
Wykład # Strona 28
-2-
Przykład:
FILE *fp;
if((fp = fopen("test.dat","w"))==NULL)
{
printf("Nie można utworzyc pliku.\n");
exit(1);
}
" Jeżeli otworzymy do zapisu istniejący plik to cała jego zawartośd zostanie stracona.
" Plik, który ma byd otwarty do odczytu musi istnied.
" Odczytywanie z pliku otwartego do odczytu/zapisu związane jest z koniecznością używania jednej
z funkcji fflush() [nie korzystamy z buforowania], fseek(), fsetpos() lub, rewind().
" Nie można wykonad operacji zapisu do operacji odczytu bez uprzedniego wywołania jednej z
powyższych funkcji, z wyjątkiem sytuacji, w której w wyniku operacji odczyt osiągnięty został
koniec pliku.
" Jednocześnie można otworzyd do FOPEN_MAX plików. Definicja wartośd znajduje się w
Zawsze należy sprawdzad, czy udało się otworzyd plik, jak również zawsze po skooczeniu
korzystania z pliku należy go zamknąd.
" int fclose (FILE *stream);
" Funkcja fclose() zamyka strumieo stream i opróżnia jego bufor.
" Po wywołaniu funkcji fclose() strumieo przestaje byd związany z plikiem i wszystkie automatycznie
alokowane bufory są zwalniane.
" Zwracaną wartością w przypadku poprawnego zamknięcia pliku jest zero. W przypadku
nipowodzenia zwracana jest wartośd EOF.
" Błędem jest próba zamknięcia pliku, który już został zamknięty.
" int fprintf (FILE *stream, const char *format, ...);
" Funkcja fprintf() wypisuje do strumienia stream wartości argumentów wymienione na liście
argumentów zgodnie z parametrem format.
" Zwracana wartośd jest równa liczbie wypisanych znaków, w przypadku błędu funkcja zwraca
wartośd ujemną.
" Działanie łaocucha formatującego jest identyczne jak w przypadku funkcji fprintf().
" int scanf (FILE *stream, const char * format, ...);
" Funkcja scanf() odczytuje dane ze strumienia stream zgodnie z parametrem format.
" Zwracana wartośd jest równa liczbie argumentów, którym udało się przypisad wartośd,
" Działanie łaocucha formatującego jest identyczne jak w przypadku funkcji scanf().
" int ftell (FILE *stream);
" Funkcja ftell() zwraca aktualną wartośd wskaznika pozycji pliku dla określonego strumienia (w
którym miejscu w danej chwili wewnątrz pliku jestem).
" W przypadku strumieni binarnych wartośd ta równa się przesunięciu wskaznika względem
początku pliku wyrażonemu w bajtach.
" W przypadku strumieni tekstowych wartośd może nie mied znaczenia innego niż argument funkcji
fseek(), ze względu na możliwe przekształcenia znaków (powrót karetki \r, nowa linia \n) W
przypadku błędu zwracana jest wartośd -1.
" int fseek (FILE * stream, long int offset, int origin);
" Funkcja fseek() ustawia wskaznik pozycji pliku związanego z określonym strumieniem
uwzględniając wartości offset i origin. Parametr offset to liczba bajtów względem pozycji
wyjściowej oznaczonej przez parametr origin. Wartośd parametru origin to jedno z poniższych
makr.
Wykład # Strona 29
-3-
- SEEK_SET - szukaj, zaczynając od początku pliku.
- SEEK_CUR - szukaj, zaczynając od aktualnej pozycji w pliku,
- SEEK_END - szukaj, zaczynając od kooca pliku
ad printf()
" Specyfikator formatu rozpoczyna się znakiem %, po którym następuje kod formatujący.
" Liczba argumentów musi byd równa liczbie specyfikatorów formatu.
" Specyfikatory formatu:
%c znak
%d lub %i dziesiętna liczba całkowita ze znakiem
%e lub %E notacja naukowa
%f dziesiętna liczba zmiennoprzecinkowa
%g używa %e lub %f, wybierając ten, który daje krótszy wynik
%o liczba ósemkowa bez znaku
%s łaocuch znaków
%u dziesiętna liczba całkowita bez znaku
%x lub %X liczba szesnastkowa bez znaku
Przykład:
%05d // liczba składająca się z mniej niż 5 cyfr zostanie uzupełniona zerami.
%10.4f // wyświetla liczbę co najmniej 10 cyfrową z czterema cyframi po kropce.
%5.7s // wypisze łaocuch zawierający co najmniej 5 znaków, ale nie więcej niż siedem.
%-10.2f // spowoduje wyrównanie do lewego brzegu 10 znakowego pola liczby
zmiennoprzecinkowej z dwoma cyframi po kropce.
%ld // wyświetlamy liczbę long int
%hu // wyświetlamy liczbę short usnigned int
ad scanf()
" Funkcja scanf() odczytuje dane ze strumienia stdin i zapisuje wartości w zmiennych wskazywanych
przez argumenty.
" Aaocuch wskazywany przez format składa się z 3 rodzajów znaków
- specyfikatory formatu
- białych znaków
- nie-białych znaków
" Specyfikatory formatu :
%c znak
%d wczytuje dziesiętną liczbę całkowitą
%i wczytuje liczbę dziesiętną ósemkową lub szesnastkową
%p wczytuje wskaznik
%n wczytuje liczbę całkowitą, równą liczbie znaków wpisanych do momentu napotkania
specyfikatora %n
%% wczytuje znak %
" Modyfikatory, których można używad w powiązaniu z kodami d, i, o ,u oraz x.
- l - wczytuje długą liczbę całkowitą
- h - wczytuje krótką liczbę całkowitą
" Specyfikatory ...
" Białe znaki w łaocuchu formatującym powodują odrzucenie przez funkcję scanf() jednego lub kilku
białych znaków ze strumienia wejściowego.
Wykład # Strona 30
-4-
" Biały znak to spacja, tabulator, lub nowy wiersz.
" Jeden biały znak powoduje wczytanie przez funkcję scanf() dowolnej liczby białych znaków aż do
pierwszego nie-białego znaku.
" Nie-biały znak w łaocuchu formatującym powoduje odczytanie i odrzucenie przez funkcję scanf()
pasującego znaku ze strumienia wejściowego.
" Znak * umieszczony po % a przed kodem formatującym spowoduje wczytanie i odrzucenie danych
określonego typu.
Przykład:
scanf("%d%*c%d", &x, &y); // dla danych 10/20 przypisze x=10, y=20
" Polecenia formatujące mogą określad maksymalną długośd pola
Przykład:
scanf("%20s", adres);
//wczytuje nie więcej niż 20 znaków do tablicy adres.
" Jeżeli w strumieniu jest więcej niż 20 znaków, to kolejne wywołanie funkcji wczytującej dane
rozpocznie się w miejscu, w którym przerwał a pracę funkcja scanf().
Wykład # Strona 31
Wykład #14
9 czerwca 2010
14:02
BIBLIOTEKI, MAKEFILE
Inżynieria oprogramowania pomaga w procesie automatyzacji tworzenia oprogramowania.
Będzie to opowieśd o narzędziu GNU - make.
" Pliki *.c + *.h -> kompilator -> *.o
" Pliki nagłówkowe włączamy za pomocą dyrektywy preprocesora #include.
" Pliki *.o + biblioteki + kod startowy -> linker -> *.exe
" gcc -o foo foo.c -lm
" gcc -c foo.c
" gcc -o foo foo.o -lm
Makefile jest przydatny zwłaszcza przy dużych projektach, kiedy po zmianie jednego pliku
zródłowego nie będzie trzeba kompilowad wszystkiego.
" Każda biblioteka składa się z dwóch części:
- pliku nazwa *.h zawierającego stałe, typy oraz prototypy funkcji znajdujących się w bibliotece.
/* sorty.h*/
#ifndef SORTY_H
#define SORTY_H
int rand(void);
void bubble_sort(int,int []);
#endif
- pliku nazwa.c zawierającego zródła biblioteki
/* sorty.c*/
#include "sorty.h"
void bubble_sort(int m, int a[]){...}
" Poleceniem gcc -c sorty.c kompilujemy bibliotekę, otrzymujemy plik sorty.o. Plik ten nie jest
plikiem wykonywalnym. Nie zawiera funkcji main().
" Poleceniem gcc -c driver.c kompilujemy plik zawierający funkcję main(), otrzymujemy plik driver.o
" Poleceniem gcc -o driver driver.o sorty.o łączymy pliki obiektowe w jeden plik wykonywalny.
" Poleceniem ./driver uruchamiamy plik wykonywalny.
" W pliku o nazwie makefile umieszczamy komendy kompilacji:
driver: driver.o sorty.o
.[TAB] gcc -o driver driver.o sorty.o
driver.o: driver.c sorty.h
.[TAB] gcc -c driver.c
sorty.o: sorty.c sorty.h
.[TAB] gcc -c sorty.c
" Wszystkie linie zawierające polecenia gcc... muszą zaczynad się od znaku tabulatora *TAB+.
" Wywołanie polecenia make spowoduje utworzenie pliku wykonywalnego driver.
" make -f name.
" W pliku makefile mogą znajdowad się:
- reguły jawne, np.
driver.o: driver.c sorty.h //driver.o zależy od driver.c i driver.h i żeby go utw. należy utw. te dwa
.[TAB] gcc -c driver.c
Wykład # Strona 32
-2-
- reguły niejawne (domyślne), np.
driver.o: sorty.h
-definicje zmiennych, np
OBJECTS = driver.o
rm $(OBJECTS)
- dyrektywy, odczytanie innego pliku makefile, komendy wyboru.
- komentarze, każda linijka zaczynająca się znakiem #
Przykład:
OBJECTS = driver.o sorty.o sel.o merge.o
driver: $(OBJECTS)
[TAB] gcc -o driver $(OBJECTS) -lm
driver.o: sorty.h sel.h merge.h
sorty.o: sorty.h
sel.o: sel.h
merge.o: merge.h
.PHONY: clean //usuwa wszystkie pliki z katalogu
clean:
rm $(OBJECTS)
// Potem po skompilowaniu jak wywoła się make clean, to usunie wszystkie pliki *.o
/* makefile (ponizszy makefile można sobie skopiowad i używad, podmieniając nazwy plików) */
# Source, Executable, Includes, Library Defines
INCL = sorty.h sel.h merge.h
SRC = driver.c sorty.c sel.c merge.c
OBJ = $(SRC:.c=.o)
LIBS = -lm
EXE = driver
# Compiler, Linker Defines
CC = /usr/bin/gcc
CFLAGS = -ansi -pedantic -Wall -O2
LIBPATH = -L.
LDFLAGS = -o $(EXE) $(LIBPATH) $(LIBS)
CFDEBUG = -ansi -pedantic -Wall -g -DDEBUG $(LDLFLAGS)
RM = /bin/rm -f
#Compile and Assemble C Source Files into Object Files
%.o: %.c
$(CC) -c $(CFLAGS) $*.c
#Link all Object Files with external Libraries into Binaries
$(EXE): $(OBJ)
$(CC) $(LDLFLAGS) $(OBJ)
#Objects depend on these Libraries
$(OBJ): $(INCL)
#Create a gdb/dbx Capable Executable with DEBUG flags turned on
debug:
$(CC) $(CFDEBUG) $(SRC)
#Clean Up Objects, Executables, Dumps out of source directory
clean:
$(RM) $(OBJ) core a.out
Wykład # Strona 33
-3-
BIBLIOTEKI STATYCZNE
" Tworzenie i kompilacja plików zródłowych: gcc -c objfile1.c ...
" Tworzenie biblioteki:
ar rc libmylib.a objfile1.o objfile2.o objfile3.o
" Tworzenie indeksu: ranlib libmylib.a
" Wykorzystanie biblioteki statycznej:
- polecenie gcc -o foo foo.o -L. -lmylib łączy pliki obiektowe z biblioteką mylib i tworzy plik
wykonywalny foo.
- Parametr -L. informuje gcc by szukad libmylib w bieżącym katalogu.
" Tworzenie biblioteki: ar vq mylib.a
myobj1.o myobj2.o
- opcja q -dołącz pliki myobj1.o myobj2.o do kooca archiwum mylib.a, o ile istnieje, bez
sprawdzania podmieniania.
- Opcja v - wypisz dodawane pliki
" Wypisz zawartośd biblioteki: ar vt mylib.a
- Opcja t - wyświetla tylko nazwę członka archiwum.
- Opcja v - listowane są atrybuty plików (prawa, timestamp, właściciel, grupa i rozmiar).
" Wstaw (z podmienianiem) pliki do archiwum: ar vr mylib.a myobj1.o myobj3.o
- Opcja r - istniejący członkowie (myobj1.o) są zastępowani ich nowymi wersjami, a nowi
członkowie (myobj3.o) są dodawani na koniec archiwum.
- Opcja v - wyświetla komentarz do każdego dodawanego pliku, wskazując czy plik został dopisany
na koniec czy podmieniony.
" Wstaw plik do archiwum w określone miejsce: ar vrb myobj1.o mylib.a myobj4.o
- Opcja b - umieszcza plik myobj4.o w archiwum mylib.a przed plikiem myobj1.o.
- Opcja a - umieszcza plik myobj4.o w archiwum mylib.a za plikiem myobj1.o
" Update archiwum: ar vru mylib.a myobj1.o
- Opcja u - wstawia tylko te z wymienionych plików, które są nowsze od istniejących członków o
tych samych nazwach.
" Zmiana kolejności plików w archiwum: ar vma myobj1.o mylib.a myobj3.o myobj4.o
- Opcja ma - umieszcza pliki myobj3.o myobj4.o w archiwum mylib.a bezpośrednio za myobj1.o
Względna kolejnośd plików myobj3.o myobj4.o nie ulega zmianie. Jeżeli nie użyto żadnych
modyfikatorów zostaną przeniesione na koniec archiwum.
- Kolejnośd członków w archiwum może byd istotna przy linkowaniu biblioteki z programami, kiedy
symbol jest zdefiniowany w więcej niż jednym pliku składowym biblioteki.
" Wyciąganie plików z archiwum: ar vx mylib.a myobj1.o
- Jeżeli nie podamy nazwy pliku to z archiwum wyciągnięte zostaną wszystkie pliki.
" Wyciąganie i zmiana nazwy pliku z archiwum: ar p mylib.a myobj3.o > my_new_obj3.o
- Opcja p - drukuje wybrany plik z archiwum na stdout. Jeżeli nie podano żadnych parametrów
wywołania wydrukowane zostaną wszystkie pliki z archiwum.
" Usuwanie plików z archiwum: ar vd mylib.a myobj1.
BIBLIOTEKI DYNAMICZNE
" Tworzenie i kompilacja plików zródłowych gcc - fPIC -c objfile1.c ...
" Tworzenie biblioteki gcc -shared -o libmylib.so objfile1.o objfile2.o objfile3.o
" Opcja -fPIC umożliwia stworzenie Position Independent Code. Biblioteki dynamiczne powinny
używad adresów względnych, ponieważ mogą byd wywoływane wielokrotnie.
" Opcja -shared służy do stworzenia zależnej od architektury dzielonej biblioteki dynamicznej.
" Polecenie gcc -o foo foo.o -L. -lmylib łączy pliki obiektowe i tworzy plik wykonywalny foo, jednakże
kod biblioteki dynamicznej / dzielonej nie jst łączony z plikiem wykonywalnym. Program, który
używa bibliotek dynamicznych, odwołuje się do nich w trakcie działania, zatem środowisko, w
którym wykonujemy dany program musi wiedzied gdzie przechowujemy biblioteki dynamiczne.
export LD_LIBRARY_PATH= /path/to/library: $(LD_LIBRARY_PATH)
Wykład # Strona 34
-4-
C99
" gcc -std=? source.c -o source
" -std - określa standard języka, dozwolone wartości dla C:
- C89, (iso9899:1990) - ISO C90 (to samo co -ansi).
- iso9899:199409 - ICO C90 (wersja zdefiniowana w amendment 1)
- c99, (iso9899:1999) - ISO C99 (standard nie jest obecnie w pełni wspierany),
http://gcc.gnu.org/gcc-4.5/c99status.html
gnu89 - domyślny, ISO C90 plus rozszerzenia GNU (między innymi kilka własności C99).
gnu99 - ISO C99 plus rozszerzenia GNU (stanie się domyślnym gdy standard ISO C99 zostanie w
pełni zaimplementowany).
" Zmiany wprowadzone w standardzie C99 dzielą się na 3 kategorie:
- możliwości dodane do standardu C89,
- możliwości usunięte ze standardu C89,
- możliwości zmienione lub rozszerzone.
Wykład # Strona 35
Wykład #15
16 czerwca 2010
14:04
C89 I C99 - RÓŻNICE
" W standardzie C99 dodano nowe słowa kluczowe:
- inline
- restrict
//Następne 3 nie są takie przydatne
- _Bool
- _Complex //liczby zespolone
- _Imaginary //^ częśd urojona
" W standardzie C99 dodano:
- tablice o zmiennym rozmiarze,
- arytmetykę na liczbach zespolonych,
- typ danych long long,
- komentarz //,
- możliwośd przeplatania kodu i danych,
- nowe elementy preprocesora,
- deklaracje zmiennych w instrukcji for,
- złożone wartości natychmiastowe
- elastyczne składowe tablicowe, elastyczne składowe struktur,
- desygnowane inicjatory,
- zmiany w rodzinie funkcji printf oraz scanf,
- predefiniowany identyfikator __func__,
- nowe biblioteki oraz nagłówki.
" W standardzie C99 usunięto:
- regułę domniemanego typu int,
-> w C89 w wielu wypadkach zakłada się typ int, jeśli typ nie jest określony explicite.
- domniemaną deklarację funkcji,
-> w C89, jeśli przed użycie funkcji nie występuje jej deklaracja, wówczas przyjmuje się jej
deklarację domniemaną.
" W standardzie C89 zmodyfikowane niektóre istniejące cechy języka:
- zwiększono limity kompilacji,
- rozszerzono typy całkowite,
- rozszerzono reguły promocji całkowitoliczbowej
- zawężono instrukcję return
KWALIFIKATOR RESTRICT
" Kwalifikator typu restrict odnosi się wyłącznie do wskazników. Stwierdza on, że wskaznik jest
jedyną drogą uzyskania dostępu do obiektu danych.
Przykład:
int tab[10];
int *wtab = tab;
restrict int *restab = (int *)malloc(10*sizeof(int));
" Wskaznik restab jest jedynym sposobem na odwołanie się do pamięci przydzielonej przez malloc.
Wykład # Strona 36
-2-
Przykład, cd.
for (int i = 0; i<10; i++)
{
wtab[i] += 5;
restab[i] += 5;
tab[i] *= 2;
wtab[i] +=3;
restab[i] += 3;
}
" Kwalifikator typu restrict umożliwia kompilatorowi lepszą optymalizację kodu.
" Kwalifikator typu restrict stosowany jest przede wszystkim jako parametry formalny funkcji, służy
też do odwoływania się do obszarów zaalokowanych przez malloc.
" Jeśli funkcja (memcpy) otrzymuje dwa wskazniki typu restrict, wówczas kompilator może założyd,
że wskazniki te wskazują na dwa różne (nienakładające się) obszary.
INLINE
" Słowo kluczowe inline odnosi się do funkcji.
" Umieszczając słowo kluczowe inline przed deklaracją funkcji, informujemy kompilator, że ma
zoptymalizowad wywołanie funkcji.
" Oznacza to z reguły, że kod funkcji zostanie wstawiony w miejscu wywołania, a jej faktyczne
wywołanie nie będzie miało miejsca.
// Wywołanie funkcji jest kosztowne. Chcemy zrobid tak, żeby funkcja była wywoływana szybko.
Przykład:
int max (int a, int b) { return a > b ? a:b; }
" Funkcje inline pozwalają tworzyd efektywniejszy kod, jednocześnie zachowując podejście
strukturalne, oparte na funkcjach.
" Jako funkcje inline powinno się deklarowad tylko małe funkcje, aby dublowanie kodu nie
powodowało nadmiernego wzrostu rozmiaru programu.
" Z reguły inline powoduje wstawienie kodu funkcji w miejsce jej wywołani, kompilator *...+
NOWE WBUDOWANE TYPY
" W standardzie C99 wprowadzono nowy typ danych _Bool, który może przechowywac wartości
1(true) oraz 0 (false).
" _Bool - jest typem całkowitym.
" W standardzie C99 dodano nagłówek , w którym znajdują się definicje makr bool, true,
false.
" Aby korzystad ze zmiennych logicznych powinno się raczej używad makr bool, true, false.
" W standardzie C99 wprowadzono możliwośd prowadzenia obliczeo na liczbach zespolonych.
" Dodano następujące typy danych zespolonych:
...
" W nagłówku znajdują się definicje makr complex oraz imaginary i je powinno się
wykorzystywad do operacji na liczbach zespolonych.
TABLICE O ZMIENNYCH ROZMIARACH
" Jedynie tablice lokalne (zasięg prototypu lub bloku) można deklarowad w ten sposób.
void f(int a, int b)
{
int tab[a][b];
}
" Wprowadzenie tablic o zmiennych rozmiarach spowodowało drobną zmianę w działaniu
operatora sizeof.
Wykład # Strona 37
-3-
" Z reguły jest to operator czasu kompilacji.
KORZYSTANIE Z MODYFIKATORÓW DOSTPU DLA TABLIC
" Standard C99 pozwala używad słowa kluczowego static wewnątrz nawiasów w deklaracji tablicy,
jeśli występuje jako parametr funkcji.
Przykład:
int fun(char str[static 80]) {...}
" Informuje to kompilator, że tablica wskazywana przez parametr będzie zawierała co najmniej
określoną ilośd elementów (tu: 80).
ZMIANY W PREPROCESORZE
" Najważniejsza zmiana w preprocesorze wiąże się z możliwością tworzenia makr o zmiennej liczbie
argumentów.
Przykład:
#define MyMax(...) max (__VA_ARGS__)
" W takim przypadku MyMax(a,b) zostanie przekształcone na max(a,b).
ZAOŻONE WARTOŚDI NATYCHMIASTOWE
" W standardzie C99 możliwe jest definiowanie złożonych wartości natychmiastowych, kóre są
wyrażeniami tablicowymi lub strukturalnymi, wyznaczającymi obiekt danego typu
Przykład:
double *fp = (double []) {1.0, 2.0, 3.0};
Powyższa instrukcja tworzy wskaznik double, o nazwie fp, wskazujący na pierwszy element
trzyargumentowej tablicy wartości typu double.
ELASTYCZNE SKAADOWE TABLICOWE
" Standard C99 pozwala zadeklarowad tablicę o nieokreślonym rozmiarze jako ostatnią składową
struktury.
" Struktura musi zawierad co najmniej ...
" Rozmiar takiej struktury zwrócony przez operator sizeof nie uwzględnia pamięci przeznaczonej na
taką tablicę.
Przykład:
struct mys
{
int a;
int b;
float fa[];
...
struct mys * p;
}
Przydział pamięci dla struktury zawierającej 10 elementową tablicę.
p = (struct mys *) malloc( sizeof(struct mys) + 10*sizeof(float) );
INICJATORY DESYGNOWANE
" Nowa cecha dodana w standardzie C99 to inicjatory desygnowane.
" Desygnatory występują w dwóch odmianach
- dla tablic: [indeks] = val,
- dla struktur .nazwa-składowej = val.
Wykład # Strona 38
-4-
int a[10] = {[0]=100, [3]=200};
struct mys
{
int a;
int b;
int c;
} ob = {.c=30, .a=10};
" Standard C99 rozszerzył możliwości funkcji printf() i scanf() o obsługę typów danych long long int
oraz usnigned long long int.
" Modyfiator formatu to ll.
" W C99 dodano modyfikator hh, którego używa się aby określid argumenty typu char, ...
NOWE BIBLIOTEKI W C99
" W standardzie C99 dodano nowe biblioteki i nagłówki:
- complex.h. - obsługa arytmetyki na liczbach zespolonych,
- fenv.h - umożliwia dostęp do flag stanu środowiska zmiennopozycyjnego oraz innych elementów
tego środowiska,
- iso646.
- inttypes.h - definiuje standardowy, przenośny zbiór nazw typów całkowitych. Wspomaga również
funkcje obsługujące liczby całkowite o maksymalnej długości.
- stdbool.h - obsługuje typy danych logicznych,
- stdint.h - definiuje standardowy, przenośny zbiór nazw typów...
- tgmath.h - definiuje makra zmiennopozycyjne ogólnego typu,
- wchar.h - wspomga funkcje obsługujące znaki rozszerzone oraz wielobajtowe,
- wctype.h - wspomaga funkcje klasyfikujące znaki rozszerzone oraz wielobajtowe.
ZWIKSZONE LIMITY TRANSLACJI
" Limit translacji - minimalna liczba poszczególnych elementów które kompilator musi obsłużyd.
ROZSZERZONE TYPY CAAKOWITE
" W standardzie C99 w nagłówku zdefiniowano kilka rozszerzonych typów całkowitych.
ZMIANY REGUA PROMOCJI
" W standardzie C89 jeżeli promowana wartośd mieści się w typie int jest promowana do in.
" W standardzie C99 każdy int ma określony stopieo.
Wykład # Strona 39


Wyszukiwarka

Podobne podstrony:
materialy wyklad pp cz 3 (2)
Wykład PP (1)
materialy wyklad pp cz 2
wyklad PP pliki
materialy wyklad pp cz 1 (2)
ZW Pol pien PP 2011 2012 odcinek 1 dla studentów slides z wykładów w dniach 02 16 10 2011
pp wyklady 2
jsas pp wyklad1
pp wyklady 5
pp wyklady 1
Podstawy automatyki wykład 1 Politechnika Poznańska PP
PP wyklady?sia
PP 2012 Program wykładu

więcej podobnych podstron