210 likes | 297 Views
10. előadás (2004. április 20.). A C előfordító (folytatás) Néhány hasznos compiler opció Egy tanulságos könyvtári függvény Változó hosszúságú argumentum lista I/O átirányítás Véletlenszám generálás Parancs végrehajtás. 1. A C fordító működésének szemléltetése. 2. A C előfordító 16.
E N D
10. előadás (2004. április 20.) • A C előfordító (folytatás) • Néhány hasznos compiler opció • Egy tanulságos könyvtári függvény • Változó hosszúságú argumentum lista • I/O átirányítás • Véletlenszám generálás • Parancs végrehajtás 1
A C előfordító 16. A parancssorban is adhatunk meg makrót: cc -DLINELENGTH=80 prog.c -o prog Hatása a következő: #define LINELENGTH 80 A #define vagy az #undef felülbírálja a parancssori beállításokat. Érték nélkül is definíálhatunk szimbólumot: cc -DDEBUG prog.c -o prog Ekkor a default érték: 1 Pl. nyomkövetésre jól használható: 3
A C előfordító 17. #ifdef DEBUG printf("Nyomkövetés: Program Verzió:1\n"); #else printf("Program Verzió:1\n"); #endif A program belsejében is használható: x = y *3; #ifdef DEBUG printf("Nyomkövetés:változók (x,y)=\n",x,y); #endif 4
A C előfordító 18. A #error fordító (compiler) hibaüzenetet generál: #ifdef OS_MSDOS #include <msdos.h> #elifdef OS_UNIX #include "default.h" #else #error Nem támogatott OS!! #endif 5
A C előfordító 19. Makródefinícióban használható a # stringesítő operátor (string-literal operator), pl.: #define OUT(x) printf(#x) Hívása: OUT(Hello Jani!); -> printf("Hello Jani!"); A speciális karakterekre tekintettel van: OUT("Hello Jani!"); -> printf("\"Hello Jani!\""); Makrókifejtéskor két string egyesítésére (konkatenáció) használható a ## konkatenáció operátor (ez nem kezeli az escape karaktereket), pl.: 6
A C előfordító 20. #define SZECSKA(x) func##x salata=SZECSKA(3)(q,w); -> salata=func3(q,w); Módosult a C kód! #include <stdio.h> #define OUT(x) printf(#x"egyenlő%d.\n",x) main() { int hossz=123; OUT(hossz); return(0); } printf("hossz""egyenlő%d.\n",hossz); hossz egyenlő 123. 7
Néhány hasznos compiler opció 1. cc program.c -> a.out -o cc -o program program.c -> program -c cc -c modul1.c modul2.c -> modul1.o, modul2.o cc -o exefajl modul1.o modul2.o -> exefajl -llibrary cc -o calccalc.c -lm (a matematikai könyvtárt explicite kell linkelni) 8
Néhány hasznos compiler opció 2. -Ldirectory cc prog.c -L/home/myname/mylibs mylib.a Különben csak a/libés/usr/libhelyeken keres. -Ipathname Az include fájlok keresési sorrendje: a forrásfájl helye, az-I-vel megadott katalógusban és végül a/usr/include-ban, pl.: -g Utasítja a compiler-t kiegészítő szimbólum tábla információk készítésére a debug eszközök használatához. 9
Egy tanulságos könyvtári függvény 1. Az stdlib.h -ban található qsort rendező függvény prototípusa: void qsort(void *base, size_t num_elements, size_t element_size, int (*compare)(void const *, void const *)); base: a rendezendő tömbre mutat num_elements: a tömb mérete (elemeinek száma) element_size: a tömb elemeinek mérete byte-okban compare: függvény mutató A qsort azáltal adattípus független, hogy az összehasonlítást a felhasználóra bízza. 10
Egy tanulságos könyvtári függvény 2. A compare függvény egész visszatérő értéke:<0, ha az első érték kisebb a másodiknál,=0, ha az első érték egyenlő a másodikkal,>0, ha az első érték nagyobb a másodiknál. Pl. rendezzük a következő struktúrát egész kulcsa szerint: typedef struct { int key; struct other_data; } Record; 11
Egy tanulságos könyvtári függvény 3. A compare függyvény definíciója: int record_comp(void const *a,void const *b) { return (((Record *)a)->key -((Record *)b)->key); } Így aqsorthívása pl.: qsort( array, array_length, sizeof(Record), record_comp); 12
Változó hosszúságú argumentum lista 1. Pl.: f(arg1, arg2, utarg,...) Az <stdarg.h> headerben deklarált függvények és változók: Az egyes argumentumokat egy va_list típusú változóval címezhetjük: va_list ap; A va_start makróval inicializálhatjuk az ap mutatót: va_start (va_list ap, utarg); A va_arg makró megadja a meg nem nevezett következő argumentumot (automatikusan lépteti ap-t): típus va_arg (va_list ap, típus); 13
Változó hosszúságú argumentum lista 2. Az f függvényben az argumentumlista feldolgozása után, de még a visszatérés előtt meg kell hívni a va_end makrót: void va_end (va_list ap); Az int printf (char *formatum, ...); pédául így készült. Egy példa (K&R): #include <stdarg.h> #include <stio.h> void minprintf (char *fmt, ...) { va_list am; 14
Változó hosszúságú argumentum lista 3. char *p, *sert; int iert; double dert; va_start (am, fmt); /* am rááll az első név nélkülire*/ for (p=fmt; *p; p++){ if (*p != '%'){ putchar (*p); continue; } switch (*++p){ case 'd': iert=va_arg(am, int) /*megadja az argumentumot és léptet*/ 15
Változó hosszúságú argumentum lista 4. printf ("%d", iert); break; case 'f': dert= va_arg(am, double); printf ("%f", dert); break; case 's': for (sert=va_arg(am, char *); sert; sert++) putchar (*sert); break; default: putchar (*p); 16
Változó hosszúságú argumentum lista 5. break; } /*switch*/ } /*for*/ va_end (am); /*a lista feldolg. lezárása*/ } /*minprintf*/ 17
I/O átirányítás 1. Bemenet: az int getchar (void) függvény a standard bemenetről olvas egy karaktert, visszatér a beolvasott karakterrel, vagy hiba esetén EOF-fel. prog <állományból (nem kerül az argv-be) pipeing mechanizmussal: masprog | prog (a masprog standard kimenete a prog standard bemenete) 18
I/O átirányítás 2. Kimenet: az int putchar (int) függvény a standard kimenetre ír egy karaktert, visszatér a kiírt karakterrel, vagy hiba esetén EOF-fel. prog >állományba (nem kerül az argv-be) vagy pipeing mechanizmussal: prog | masprog (a prog standard kimenete a masprog standard bemenete) 19
Véletlenszám generálás Az <stdlib.h> header-ben: int rand (void); 0 <= r <= RAND_MAX 1-ről indul, min. RAND_MAX= 32767 void srand (unisgned int start); 0 <= r < 1 #define frand()((double)rand()/(RAND_MAX +1.0)) 20
Parancs végrehajtás Az <stdlib.h> -ban int system (const char *s); s az operációs rendszertől függő parancs, pl.: system ("date"); Visszatérési értéke Unix-ban az exit visszatérési értékkel egyezik meg. 21