Jeszcze o funkcjach i strukturze projektu Zak lad Chemii Teoretycznej UJ 3 grudnia 2008
1 2 3 4 5
typedef Plan typedef specyfikator typu nazwa S luży do stworzenia nowej nazwy dla jakiegoś typu. Nazwa ta b edzie mog la być używana we wszystkich miejscach, w których użylibyśmy oryginalnego specyfikatora typu. t y p e d e f double zarobki ; t y p e d e f char * Napis ; t y p e d e f Napis m i e s i a c e [ 3 ] ; //?? z a r o b k i a ; z a r o b k i *b [ 1 0 ] ; Napis c = a l a ; m i e s i a c e l a t o, j e s i e n = w r z e s i e n, p a z d z i e r n i k, l i s t o p a d ;
Definiowanie typ zwracanej wartości ( nazwa wskaźnika)(lista typów argumentów) Funkcja, podobnie jak zmienna, musi mieć swoje określone miejsce w pamieci. Jeśli tak to z funkcja kojarzony jest adres, i nie ma przeszkód, żeby wskazywa l na nia wskaźnik. Typ wskaźnika na funkcje jest określony przez typ zwracanej wartości i liste typów argumentów.
Jak ich używać? v o i d m y i n t f u n c ( i n t x ) p r i n t f ( %d\n, x ) ; i n t main ( ) v o i d (* f o o ) ( i n t ) ; f o o = &m y i n t f u n c ; // p r z y p i s a n i e a d r e s u do w s k a z n i k a foo = my int func ; // mozna i tak f o o ( 2 ) ; // wywolujemy tak (* f o o ) ( 2 ) ; // a l b o tak r e t u r n 0 ;
Po co ich używać? /* b i b l i o t e c z n a f u n k c j a s o r t u j a c a */ v o i d q s o r t ( v o i d * f i e l d, s i z e t nelements, s i z e t sizeofanelement, i n t (* cmpfunc ) ( c o n s t v o i d *, c o n s t v o i d * ) ) ; v o i d q s o r t (..., i n t (* cmpfunc ) ( c o n s t v o i d *, c o n s t v o i d *)) /* sortowanie uwaga item1, item2 sa typu void* */ i n t b i g g e r = cmpfunc ( item1, item2 ) ; // c a l l b a c k /* u z y c i e wyniku */
Na bia lym koniu #i n c l u d e < s t d l i b. h> // q s o r t #i n c l u d e <s t d i o. h> // p r i n t f i n t CmpFunc ( const void* a, const void* b ) c o n s t i n t * a = a ; c o n s t i n t * b = b ; i f (* a > *b ) r e t u r n 1 ; e l s e i f (* a == *b ) r e t u r n 0 ; e l s e r e t u r n 1; i n t main ( ) i n t f i e l d [ 1 0 0 ] ; for ( i n t i = 0 ; i < 1 0 0 ; i ++) f i e l d [ i ] = i % 7 ; q s o r t ( f i e l d, /* l i c z b a elementow */ 100, /* r o z m i a r elementu */ s i z e o f ( f i e l d [ 0 ] ), /* w s k a z n i k na f u n k c j e porownujaca */ CmpFunc ) ; for ( i n t i = 0 ; i < 1 0 0 ; i ++) p r i n t f ( e l e m e n t #%d to %d\n, i +1, f i e l d [ i ] ) ; r e t u r n 0 ;
Co oznaczaja argc i argv Nag lówek funkcji main może wygladać tak: i n t main ( i n t argc, char * a r g v [ ] ) argc przechowuje liczb e argumentów, z jakimi program zosta l wywo lany, sama nazwa programu jest również takim argumentem argv jest wskaźnikiem do tablicy zawierajacej argumenty, każdy argument jako osobny napis argv[0] zawiera nazw e programu argv[argc] jest wskaźnikiem na NULL
Przyk lad użycia - wypisanie zawartości pliku Wywo luj e nazwa programu nazwa pliku #i n c l u d e <s t d i o. h> i n t main ( i n t argc, char * a r g v [ ] ) i f ( a r g c!= 2) /* a r g c powinno w y n o s i c 2 */ /* J e s l i n i e, to wypiszmy i n f o r m a c j e */ p r i n t f ( usage : %s f i l e n a m e, a r g v [ 0 ] ) ; e l s e FILE * f i l e = f o p e n ( a r g v [ 1 ], r ) ; /* f o p e n zwraca 0 (NULL) j e s l i s i e n i e p o w i e d z i e */ i f ( f i l e == 0) p r i n t f ( Could not open f i l e \n ) ; e l s e i n t x ; w h i l e ( ( x = f g e t c ( f i l e ) )!= EOF) p r i n t f ( %c, x ) ; f c l o s e ( f i l e ) ;
stdarg.h Plan i n t p r i n t f ( char *fmt,... ) Funkcje tego rodzaju można wywo lać z różna liczba argumentów, różnych typów. Plik nag lówkowy stdarg.h deklaruje typ va list i definiuje trzy makra, iterujace poprzez liste argumentów, których liczba i typy nie sa znane wywo lanej funkcji. v o i d v a s t a r t ( v a l i s t ap, l a s t ) ; t y p e v a a r g ( v a l i s t ap, t y p e ) ; v o i d va end ( v a l i s t ap ) ; v o i d v a c o p y ( v a l i s t dest, v a l i s t s r c ) ; Wywo lana funkcja musi zadeklarować obiekt typu va list, który jest używany przez makra va start, va arg, va end i va copy.
Przyk lad użycia - wyznaczanie średniej #i n c l u d e <stdarg. h> #i n c l u d e <s t d i o. h> double a v e r a g e ( i n t num,... ) v a l i s t a r g s ; double sum = 0 ; /* I n i c j a l i z a c j a a r g s na p i e r w s z y argument po num*/ v a s t a r t ( args, num ) ; /* Sumowanie wszystkich argumentow, polegamy na wywolaniu d l a o k r e s l e n i a i c h l i c z b y */ for ( i n t x = 0 ; x < num ; x++ ) sum += v a a r g ( args, double ) ; va end ( args ) ; // c z y s c i m y a r g s r e t u r n sum / num ; i n t main ( ) p r i n t f ( %f \n, a v e r a g e ( 3, 1 2. 1, 0. 2, 1 3. 1 ) ) ; p r i n t f ( %f \n, a v e r a g e ( 5, 3. 3, 2. 2, 1. 1, 5. 5, 3. 3 ) ) ;
Przyk lad użycia - formatowanie #i n c l u d e <s t d i o. h> #i n c l u d e <stdarg. h> v o i d f o o ( char *fmt,... ) v a l i s t ap ; i n t d ; char c, *p, * s ; v a s t a r t ( ap, fmt ) ; w h i l e (* fmt ) s w i t c h (* fmt++) case s : /* n a p i s */ s = v a a r g ( ap, char * ) ; p r i n t f ( s t r i n g %s \n, s ) ; break ; case d : /* i n t */ d = v a a r g ( ap, i n t ) ; p r i n t f ( i n t %d\n, d ) ; break ; case c : /* c h a r */ c = ( char ) v a a r g ( ap, i n t ) ; p r i n t f ( c h a r %c \n, c ) ; break ; va end ( ap ) ;
Naiwne(?) obserwacje program może być budowany z wielu plików źród lowych program musi zawierać dok ladnie jedna funkcje main żeby móc wykorzystać jakieś funkcje w innych programach nie moga one znajdować sie w tym samym pliku co funkcja main użycie funkcji wymaga ich wcześniejszych deklaracji
Przydatne opcje kompilatora -c gcc -c calc.c gcc -o calc calc.o -llibrary gcc calc.c -o calc -lm -Ldirectory gcc prog.c -L/home/myname/mylibs mylib.a -Ipathname gcc prog.c -I/home/myname/myheaders -Didentifier #define identifier -Dsymbol=name #define symbol name
Różne oblicza kompilacji // k o m p i l a c j a do p l i k u o b i e k towego gcc c o f. o f. c // budowanie programu z uzyciem w i e l u p l i k o w gcc c o f i l e 1. o f i l e 1. c gcc c o f i l e 2. o f i l e 2. c gcc c o main. o main. c gcc o main main. o f i l e 1. o f i l e 2. o // budowanie b i b l i o t e k i gcc c o f 1. o f 1. c gcc c o f 2. o f 2. c gcc c o f 3. o f 3. c a r r l i b f o o. a f 1. o f 2. o f 3. o r a n l i b l i b f o o. a
Używanie bibliotek // budowanie z l i n k o w a n i e m z a w a r t o s c i b i b l i o t e k gcc c o f 1. o f 1. c gcc c o f 2. o f 2. c gcc c o f 3. o f 3. c a r r l i b f o o. a f 1. o f 2. o f 3. o r a n l i b l i b f o o. a gcc c o prog. o prog. c gcc o prog prog. o L. l f o o l b a r
Dyrektywa preprocesora include Do l acza do pliku, w którym sie znajduje zawartość wskazanego przez nia pliku /* s z u k a j w l o k a l i z a c j a c h systemowych */ #i n c l u d e <plik naglowkowy do dolaczenia > /* z a c z n i j w y s z u k i w a n i e od k a t a l o g u, w ktorym z n a j d u j e s i e kompilowany p l i k */ #i n c l u d e p l i k n a g l o w k o w y d o d o l a c z e n i a /* s c i e z k i b e z w z g l e d n e */ #i n c l u d e / u s r / i n c l u d e / p l i k n a g l o w k o w y. h #i n c l u d e C: \ \ b o r l a n d \ i n c l u d e s \ p l i k n a g l o w k o w y. h /* s c i e z k i wzgledne */ #i n c l u d e katalog1 / plik naglowkowy. h #i n c l u d e.. / k a t a l o g 1 / k a t a l o g 2 / p l i k n a g l o w k o w y. h
Pliki nag lówkowe \\ f 1. c double f 1 ( double * a, i n t n )... \\ f 2. c double f 2 ( double x )... \\ f 3. c i n t f 3 ( char *a )... \\ f o o. h p l i k naglowkowy double f 1 ( double *, i n t ) ; double f 2 ( double ) ; i n t f 3 ( char * ) ; /* dolaczany dyrektywa #include, tam gdzie bedziemy uzywac f u n k c j i z b i b l i o t e k i f o o */
Problemy z plikami nag lówkowymi // p l i k a. h i n t a ( i n t ) ; // p l i k b. h #i n c l u d e a. h i n t b ( i n t ) ;... // p l i k main. c #i n c l u d e a. h #i n c l u d e b. h /* Oops, funkcja a j e s t deklarowana dwukrotnie. W tym wypadku n i e g r o z n e, a l e z u p e l n i e n i e p o t r z e b n e */
Jak ich uniknać? Plan // p l i k a. h #i f n d e f A H #d e f i n e A H i n t a ( i n t ) ; #e n d i f // p l i k b. h #i f n d e f B H #d e f i n e B H #i n c l u d e a. h i n t b ( i n t ) ;... #e n d i f // p l i k main. c t e r a z j e s t OK #i n c l u d e a. h #i n c l u d e b. h