Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

1 Krasjkurs i C (pluss litt matlab). 2 Innhold –Litt om Matlab –Funksjoner –Strukturer (Structs) –Noen matlab-funksjoner dere kan få bruk for – C –Kompilatorer.

Liknende presentasjoner


Presentasjon om: "1 Krasjkurs i C (pluss litt matlab). 2 Innhold –Litt om Matlab –Funksjoner –Strukturer (Structs) –Noen matlab-funksjoner dere kan få bruk for – C –Kompilatorer."— Utskrift av presentasjonen:

1 1 Krasjkurs i C (pluss litt matlab)

2 2 Innhold –Litt om Matlab –Funksjoner –Strukturer (Structs) –Noen matlab-funksjoner dere kan få bruk for – C –Kompilatorer –Kompilering –C syntaks –Funksjoner i C –Variable i C –Operatorer i C –Pekere –Arrays og Strukturer –Makroer –Dynamisk Minne-allokering –Lesing og skriving av binær fil, eksempel på å lese en wav-fil i C. (Nyttig for oppgaven..!) Om du ønsker, kan du sette inn navn, tittel på foredraget, o.l. her.

3 3 Matlab –Antar en del kunnskap i matlab: For mer grundig introduksjon henvises til: nts/MatlabIntro.pdf nts/MatlabIntro.pdf –Matlab skiller seg fra språk som java og C ved at matlab prosesserer linje for linje, –Matlab håndterer mange oppgaver, som du selv må ha kontroll på i C! (håndtering av datatyper, minneallokering o.l) –Matlab er bra til simulering pga. enkel syntaks, koden er enkel å debugge, og det finnes mange funksjoner for visualisering av data. –Matlab har mange ferdiglagde funksjoner, men tenk på å skrive matlab kode som uten for store endringer kan skrives om til C ! Om du ønsker, kan du sette inn navn, tittel på foredraget, o.l. her.

4 4 Funksjoner i Matlab function ssum =geom(a,N) % funksjon som beregner summen til en % geometrisk rekke n=0:N; ssum= sum(a.^n) Funksjons- argumenter Variabel (ev. variable) som skal returneres. “geom()” er en funksjons-navnet. Funskjonen må lagres som geom.m Kommentarer i Matlab beynner med % En funksjon er en “.m” fil som starter med function. Funksjon kan ta variable inn, utføre en eller flere operasjoner, og returnere et vilkårlig antall variable. Akkurat som funksjoner i java eller C

5 5 Strukturer i Matlab struct: Ikke så forskjellig fra et objekt i java, men en struct er uten metoder. En struct består av av felter med tilhørende verdier, der de forskjellige feltene kan inneholde forskjellige datatyper. >>opt=struct('gamma',0.9,'nbits',4,'stepsize',2.0) opt = gamma: nbits: 4 stepsize: 2 >> opt.gamma ans = >> opt.alpha=0.9 opt = gamma: nbits: 4 stepsize: 2 alpha: Felter blir aksessert med ‘.’ notasjon. Nye felter kan enkelt legges til. Struct er en grei datatype å bruke for å samle tilhørende data.

6 6 Noen matlab-funksjoner dere kanskje får bruk for Wavrecord: Ta opp lyd i matlab. Wavread: Les inn en ’wav’-fil til en vektor i matlab Wavwrite: skriv en vektor til en ’wav’-fil Soundsc: Spill av en vektor i matlab Wavplay: Spill av en wavfil i matlab (Kan også gjøres med først wavread og deretter soundsc) Randn: Generer normalfordelte tilfeldige tall i matlab, kan brukes når støy-generatoren skal implementeres Er du usikker på hvordan disse funskjonene brukes, skriv help funksjonsnavn i matlab.

7 7 C-Kompilator C er i motseteting til matlab et kompilatorspråk på samme måte som java (javac). C-kompilatorer finnes gratis tilgjengelig på internett. I prinsippet kan dere bruke den dere liker best.. Forslag: –Gnu’s kompilator gcc. Denne er egentlig laget for unix, men kan kjøres på windows i et program som heter cygwin Fremgangmåte i windows: –Innstaller Cygwin –Et tips er å legge katalogen hvor bin-filen til cygwin ligger (vanligvis C:/cygwin/bin) i environment-variablen ”system path”, slik at kompilatoren gcc kan kjøres uansett hvilken katalog man er i. –Får du ikke kompilatoren til å fungere, kom å spør oss om hjelp!

8 8 Kompilering med gcc Kjør kompilatoren for å konvertere programmet fra kildekoden til en binær kjørbar fil: $ gcc my_program.c –o my_program Opsjonen –o betyr at det lages en fil som heter my_program.exe i windows, eventuelt my_program.out i unix. Hvis ikke denne brukes lages en fil med navn a.out (som er default) Det kan være lurt å lage en makefil som definerer regler for kompilering og lenking av alle filer som inngår i et program. Da kan hele systemet enkelt kompileres med å skrive make. Mer om hvordan man lager en slik makefil neste gang. Kan programmet ha mer enn en c fil?

9 9 Kompilator #include /* The simplest C Program */ int main(int argc, char **argv) { printf(“Hello World\n”); return 0; } Program __extension__ typedef unsigned long long int __dev_t; __extension__ typedef unsigned int __uid_t; __extension__ typedef unsigned int __gid_t; __extension__ typedef unsigned long int __ino_t; __extension__ typedef unsigned long long int __ino64_t; __extension__ typedef unsigned int __nlink_t; __extension__ typedef long int __off_t; __extension__ typedef long long int __off64_t; extern void flockfile (FILE *__stream) ; extern int ftrylockfile (FILE *__stream) ; extern void funlockfile (FILE *__stream) ; int main(int argc, char **argv) { printf(“Hello World\n”); return 0; } Kompileringer skjer i to steg: Preprossesering og kompilering. I preprossesering blir kildekoden ekspandert til lengre kode som er enklere for kompilatorene å forstå. Alle linjer som start med # blir tolket av preprosessoren #include inkluderer en fil. #define definerer en makro. Kommentarer blir fjernet ( /* */, // ) kodelinjer over flere linjer blir satt sammen til en linje ( \ ) Preprosessering Kompilering Kompilatoren endrer så teksten til binær kode som CPU’en kan kjøre direkte

10 10 C Syntax, og Hello World #include /* The simplest C Program */ int main(int argc, char **argv) { printf(“Hello World\n”); return 0; } int main() funksjonen er alltid! Det stedet hvor programmet starter å kjøre. (Uavhengig hvor main funksjonen finnes i koden) #include setter inn en fil. “.h” filer er såkalte “header-filer”. Header-filer definerer grensenittet (interface i java) til bibliotek og kode i andre c-filer. stdio.h er et av de vanligste biliotekene brukt u C, og inneholder funskjoner for standard input and output. Kommentarer i C beynner med /* og avsluttes med */. Blokker med kode markeres med { … }. En blokk eller et skop har egne lokale variable, som bare er tilgjengelige innenfor blokken Skriv ut en melding til “stdout”. ‘\n’ betyr ny linje. Alle “Statements” må avsluttes med semikolon. Returner ‘0’. main() returnerer enten 0 eller 1, der programmet kan returnere 1 til operativsystemet hvis det har oppstått en feil. Hva menes med ?

11 11 Funksjoner #include /* The simplest C Program */ int main(int argc, char **argv) { printf(“Hello World\n”); return 0; } Funksjons- argumenter Return type, or void Å kalle en funksjon “printf()” er bare en annen funksjon, som main(). Den er definert i “biblioteket” stdio.h, en samling funksjoner som kan kalles fra programmet. Funksjoner i C er veldig likt funksjoner i java. Man sender Argumenter til funksjonen og den retunerer en Verdi. “main()” er en funksjon. Returnering av verdi

12 12 Hva er en Variabel char x; char y=‘e’; En Variabel navngir en plass i minnet hvor man lagrer en Verdi av en bestemt Datatype. SymbolAddrVerdi x4? y5‘e’ (101) Man Deklarerer en variabel ved å gi den et navn og ved å spesifisere datatypen, eventuelt kan man sette en initialverdi (startverdi) Datatypen er en enkelt char (“character”) extern? static? const? Navn Hvilke navn kan brukes? Initiell verdi Initiell verdi til x er udefinert Kompilatoren legger dem et sted i minnet. Symbol-tabell

13 13 Hva er minne? Datamaskin-minne kan sammenlines med en stor tabell med nummererte bokser. AddrValue ‘H’ (72) 5‘e’ (101) 6‘l’ (108) 7 8‘o’ (111) 9‘\n’ (10) 10‘\0’ (0) Nummeret til boksen er Addressen. En byte kan lagres i hver boks Noen “logiske” datatyper bruker mer enn en boks, slik som strengen “Hello\n” som består av flere “charcters”, altså en tabell av datatypen char. 72? En Datatype navngir en logisk måte å lagre verdier i minnet of memory. Noen datatyper er: char char [10] int float int64_t en enkelt char (1 slot) En tabell med 10 char’s signed 4 byte integer 4 byte floating point signed 8 byte integer Ikke alltid… Signed?…

14 14 Mer om datatyper og minne. char x; char y=‘e’; int z = 0x ; Forskjellige datatyper bruker forskjellige mengde minne. De fleste datamaskin- arkitekturer lagrer på et heltallig multiplum av størrelsen på en primitiv datatype.(int,char) SymbolAddrValue x4? y5‘e’ (101) 6 7 z x betyr at konstanten er skrevet i hex (16- tallsystem,0..9,A..,F) En “vanlig” int bruker 4 bytes (dvs 32 bit integer) “padding”

15 15 Skopet til en variabel Alle Variable er definert innefor et “skop”. En Variabel kan ikke refereres utenfor dette skopet. Skopet til funksjons-argumentene er kun inne i funskjonen, dvs. innenfor klammeparantesene til funksjonen. void p(char x) { /* p,x */ char y; /* p,x,y */ char z; /* p,x,y,z */ } /* p */ char z; /* p,z */ void q(char a) { char b; /* p,z,q,a,b */ { char c; /* p,z,q,a,b,c */ } char d; /* p,z,q,a,b,d (not c) */ } /* p,z,q */ (Returner ingenting) Skopet til variablene definert inne i en funksjon starter ved definisjonen og slutter ved slutten av Skopet til en variabel defineres med klammeparanteser { }, som i java, og tilsvarer begin-end i matlab. Kalles også en blokk Skopet til variable definert utenfor funksjonen starter ved definisjonen og slutter på slutten av filen, kalt gloable variable. legal? char b?

16 16 Sammenligning og matematiske operatorer == equal to < less than <= less than or equal > greater than >= greater than or equal != not equal && logical and || logical or ! logical not + plus - minus * mult / divide % modulo Obs: Deling: Hvis andre argument er integer, så vil resultatet bli integer !! (rounded): 5 / 10  0, mens 5 / 10.0  0.5 & bitwise and | bitwise or ^ bitwise xor ~ bitwise not << shift left >> shift right Obs: Forskjell på & and &&.. 1 & 2  0 mens 1 && 2 

17 17 Mer om operatorer i C x = y assign y to x x++ post-increment x ++x pre-increment x x-- post-decrement x --x pre-decrement x Merk forskjellen på ++x og x++: Ikke bland tilordningsoperator =, og sammenligningsoperator == int x=5; int y; y = ++x; /* x == 6, y == 6 */ int x=5; int y; y = x++; /* x == 6, y == 5 */ int x=5; if (x=6) /* always true */ { /* x is now 6 */ } /*... */ int x=5; if (x==6) /* false */ { /*... */ } /* x is still 5 */ x += y assign (x+y) to x x -= y assign (x-y) to x x *= y assign (x*y) to x x /= y assign (x/y) to x x %= y assign (x%y) to x

18 18 “While” og “for” syntaks i C float pow(float x, uint exp) { float result=1.0; int i; for (i=0; (i < exp); i++) { result = result * x; } return result; } int main(int argc, char **argv) { float p; p = pow(10.0, 5); printf(“p = %f\n”, p); return 0; } float pow(float x, uint exp) { float result=1.0; int i; i=0; while (i < exp) { result = result * x; i++; } return result; } int main(int argc, char **argv) { float p; p = pow(10.0, 5); printf(“p = %f\n”, p); return 0; } “for” løkka kan ses på som en kortversjon av en while-stuktur

19 19 Kan en funksjon modifisere argumentene? Hva om vi ønsket å implementere en funksjon pow_assign() som modifiserer argumentet, slik at disse er ekvivalente: float p = 2.0; /* p is 2.0 here */ pow_assign(p, 5); /* p is 32.0 here */ float p = 2.0; /* p is 2.0 here */ p = pow(p, 5); /* p is 32.0 here */ void pow_assign(float x, uint exp) { float result=1.0; int i; for (i=0; (i < exp); i++) { result = result * x; } x = result; } Ville dette fungere? Nei! I C, blir alle argumenter sendt som verdier, og skopet til den modifiserte variabelen er bare innenfor funskjonen Men, hva om vi sendte argumentet som adressen til variabelen?

20 20 Å sende adresser SymbolAddrValue char x4‘H’ (72) char y5‘e’ (101) Hva om vi hadde en måte å finne adressen til en variabel, og så referere til minnet med adressen. address_of(y) == 5 memory_at[5] == 101 void f(address_of_char p) { memory_at[p] = memory_at[p] - 32; } char y = 101; /* y is 101 */ f(address_of(y)); /* i.e. f(5) */ /* y is now = 69 */

21 21 En ny datatype: Pekere Dette er akkurat hvordan pekere virker. “addressen til”/ referingsoperator: & “verdien til”/ dereference operator: * void f(char * p) { *p = *p - 32; } char y = 101; /* y is 101 */ f(&y); /* i.e. f(5) */ /* y er nå = 69 */ void f(address_of_char p) { memory_at[p] = memory_at[p] - 32; } char y = 101; /* y is 101 */ f(address_of(y)); /* i.e. f(5) */ /* y er nå = 69 */ En “peker type”: peker til char Pekere brukes i C for til mange ting: Sende store objekter uten å kopiere dem Aksessere dynamisk allokert minne Referere til funksjoner

22 22 “Pointers” Eksempel på pekere “addressen til” : & “verdien til”: * void f(char * p) { *p = *p - 32; } char y = 101; /* y is 101 */ f(&y); /* i.e. f(5) */ /* y is now = 69 */ void f(address_of_char p) { memory_at[p] = memory_at[p] - 32; } char y = 101; /* y is 101 */ f(address_of(y)); /* i.e. f(5) */ /* y is now = 69 */ Input er en peker til char En tommelfinger-regel er at hvis input-variablene som sendes til funksjonn skal endres i funksjonen, må de sendes som pekere. Hvis de ikke endres bør de sendes til funksjonen som verdier. NB!: Bruker man pekere som input til funksjoner er det veldig viktig å huske å sende adressen og ikke verdien, da man i tilfelle vil endre på en helt tilfeldig plass i minnet, som kan føre til at hele systemet krasjer.

23 23 Eksmpel på pekere int *p; er en peker til en integer. En stjerne i forkant av variabelnavnet deklarerer variabelen til å være en peker til den deklarerte typen (her int) int *p, q deklarerer en peker til int (p), og en int (q). p=&q lagrer adressen til q i p int a; a=*p * er også dereferingsoperator, som betyr verdien til p, altså verdien som ligger i addressen p peker på. I dette tilfellet vil altså variablen a få verdien til q

24 24 Arrays Arrays i C er en tabell med data av samme datatype, der data blir lagt i minnet etter hverandre. /* define an array of 10 chars */ char x[5] = {‘t’,’e’,’s’,’t’,’\0’}; /* accessing element 0 */ x[0] = ‘T’; /* pointer arithmetic to get elt 3 */ char elt3 = *(x+3); /* x[3] */ /* x[0] evaluates to the first element; * x evaluates to the address of the * first element, or &(x[0]) */ /* 0-indksert */ #define COUNT 10 char y[COUNT]; int i; for (i=0; i

25 25 Repetisjon, pekere og arrays int main(int argc,char **argv) { int *p ; int a=5; p=&a printf("Addressen til p: %d\n",p); printf("Addressen til a: %d\n",&a); printf("Verdien i p: %d\n",(*p)); printf("Addressen til p: %d\n",(&p)); a=p; /* Kompilator gir warning!*/ printf("Verdien til a: %d\n",&a); a=3; printf("Verdi til p: %d\n",(*p)); printf("Verdien p[0]!: %d\n",p[0]); int c[5]; c[0]=0; c[2]=2; printf("Verdien til \"c\": %d\n",c); printf("addressen til c: %d\n",&c); printf("addressen c[0]: %d\n",(&c[0])); printf("addressen c[1]: %d\n",&c[1]); printf("addressen c[2] : %d\n",&c[2]); printf("Verdi c[0]: %d\n",c[0]); printf("Verdi c[2]: %d\n",c[2]); return 0;} c=&c=&c[0] som er adressen til det første elementet. c er altså egentlig en peker til det første elementet arrayet. Selv om p ikke er definert som et array kan p tolkes som et endimensjonalt array, og verdien til p kan refereres med p[0]. Når a settes til p, blir a lik adressen lagret i p, som ofte er et veldig stort tall. Kompilatoren vil gi en warning om at et int blir satt til en pekerverdi uten ”casting”. Selv om ikke a er en peker kan addressen refereres med &a Setter a til verdien 3, som også medfører at p peker på verdien 3. (p peker på a).

26 26 Lese og skrive til fil Før en fil kan bli aksessert, må den åpnes med fopen. Fopen returner en peker til en definert datatype FILE (eller en null-peker hvis noe går galt) int main(int argc,char **argv) { FILE *f,*f_new; /*2 filpeker2*/ long offset=44; f=fopen("ae_a01.wav","rb"); f_new=fopen(“test.wav",“wb"); fseek(f,offset,0); short value[1]; /*buffer*/ for (int i=0;i<100; i++) { fread(&value,sizeof(short),1,f); printf("%d\n",value[0]) fwrite(&value,sizeof(short),1,f_new); } fclose(f); return 0; } En “.wav” inneholder 44 bit som er info om lydfilen. (Samplefrekvenes o.l, som egentlig også burde vært lest). For å lese selve taledataene flyttes “posisjonen” til filpekeren med funksjonen fseek. Dataene I en wav-fil er normalt int16 (16 bits int), dvs. en short i C (2 byte). ’rb’ vil si å åpne en binær fil for lesing, ’wb’ for å åpne for skriving. (Og ev. lage filen hvis den ikke eksisterer) fclose lukker filen og sletter filpekeren. Funksjonen fread tar inn en adresse/peker (&value), og leser N (i dette tilfellet 1) * size (sizeof(short)) fra filen definert med filpekeren f.

27 27 Casting i C Noen ganger ønsker man en variabel av en bestemt type (x bytes), og så tilordne denne til en variabel av en annen datatype (y bytes). Dette kalles “(type)casting”. #include int main() { char c; int i; float f; c = 'a'; i = c; f = i; printf("c = %d (%c)\n",c,c); printf("i = %d (%c)\n",i,i); printf("f = %f\n", f); double x= int y,y2; y=(int) x; Y2=(int) round(x); printf(”x = %lf\n", x); printf(”y = %d\n", y); printf(”y2 = %d\n", y); int *p; int q=5; q=p; //kompilator gir warning q=(int) p; //ingen warning } Enkle eksempler er å gjøre en char om til en int, og en int om til en float. Dette kan gjøres bare med vanlig tilordning i C. Både i=c og f=i er en ”typecast”-operasjon. En casting fra double/float til int gjør at verdien bli rundet av nedover. (kutter desimalene) Casting gjøres ved å skrive den nye typen i parantes foran variabelnavnet. Selv om c gjør noen “typecasts” automatisk, er det en god regel å “caste” hvis vi er i tvil, som er en måte å si til kompilatoren at vi (tror vi) vet hva vi holder på med.

28 28 Strenger i C En string i C er definert som en nullterminert array av char, det vil si en array av typen char med en “0”-char til slutt for å definere slutten på strengen #include int main(int argc,char **argv){ FILE *fp; char id[5]; fp = fopen("h wav","rb"); fread(id, sizeof(char), 4, fp); id[4]=’\0’; //id[4]=0x00; id[4]=0; if (strcmp(id, "RIFF")){ printf(“Dette er en Wavfil”) /* Noen flere strenger */ const char* navn1=”Hans”; char navn2[10]={’H’,’a’,’n’,’s’,’\0’} navn2=”Petter”; /* Ikke mulig!’/ navn2[4]=’a’; navn2[5]=’\0’; printf(”%s\n”,navn2); } De 4 første bytene i et en wav-fil, er av typen char og inneholder tegnene: RIFF. Hvis vi ønsker å lese inn de 4 første bytene og lagre dem i en streng trenger vi en tabell av størrels 5, i og med at vi må ha en ”nullbyte” til slutt! Det er flere måter å definere en streng på I C. Men obs! Forskjell på initsialiserig av en streng og tilordning, En streng må håndteres som en array av char..!

29 29 Strukturer struct: En måte å sette sammen eksisterende typer til en struktur. #include /* declare the struct */ struct my_struct { int counter; float average; struct timeval timestamp; uint in_use:1; uint8_t data[0]; }; /* define an instance of my_struct */ struct my_struct x = { in_use: 1, timestamp: { tv_sec: 200 } }; x.counter = 1; x.average = sum / (float)(x.counter); struct my_struct * ptr = &x; ptr->counter = 2; (*ptr).counter = 3; /* equiv. */ structen timeval er definert i denne h-filen. En struct kan inneholde andre structer Fields kan spesifisere spesifikke bit- størrelser. A ny-definert struct initialiseres med klammeparanteser. Alle felt som ikke blir satt, blir satt til 0 En struct definerer en struktur med fields Fields blir aksessert med ‘.’ notasjon. En peker til en struct. Felter blir aksessert med ‘->’ notasjon, eller (*ptr).counter Pakking?

30 30 Input fra kommandolinja #include int main(int argc, char** argv) /*f.eks c:\ cmdline -a 2 -b 3.0 kjører programmet cmdline*/ /* main vil motta argc=7 argv[0]=cmdline argv[1]=-a argv[2]=2 argv[3]=-b argv[4]=3.0 */ /* Start at i = 1 to skip the cmd name.*/ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') {//check next char switch (argv[i][1]) { case 'a': a_value=atoi(argv[++i]);break; case 'b': b_value=atof(argv[++i]);break; default: fprintf(stderr, "Unknown switch %s\n", argv[i]); } main-funksjonen tar inn to variable fra kommandolinja ved definsjon, argc er antall strenger som er blitt skrevet, mens char ** argv er en peker til streng, og kan ses på som en tabell av strenger. ”argv” inneholder alle strenger som er blitt skrevet på kommandolinja, inkludert program- navnet(argv[0]) En vanlig konvensjon for input-parametre, er å angi en input med en ”switch” som vil si en ”-” og så et navn for opsjonen. Deretter kommer verdien som ønskes som input til programmet. Å navngi input-opsjonene er bra for at programmet skal kunne håndtere input- verdiene på en robust måte, samtidig som det er brukervennlig. Funksjonene atoi og atof er definert i stdlib.h og konverterer en streng til hhv. int og double

31 31 Makroer Makroer blir utført av preprosessoren i kompilatoren, som ekspanderer koden ved å sette inn de definerte makroene. Makroer er en måte å gjøre koden lettere å lese gjør koden lettere å lese, men hvis mulig: bruk heller en static inline funksjon. Makroer og static inline funksjoner må inkluders i en hver fil som bruker dem, som regel ved en header-fil. Vanlig bruk for makroer: /* Makroer brukes for å definere kontsanter */ #define FUDGE_FACTOR 45.6 #define MSEC_PER_SEC 1000 #define INPUT_FILENAME “my_input_file” /* Makroer brukes for å gjøre aritmetikk med konstanter */ #define TIMER_VAL (2*MSEC_PER_SEC) /* Makroer brukes for å hente informasjon fra kompilatoren */ #define DBG(args...) \ do { \ fprintf(stderr, “%s:%s:%d: “, \ __FUNCTION__, __FILE__, __LINENO__); \ fprintf(stderr, args...); \ } while (0) /* ex. DBG(“error: %d”, errno); */ Float konstanter må ha et komma, ellers er de av typen int Sett beregningene i parentes. Hvorfor? Makroer over flere linjer må deles opp med \ Sett makroer over flere linje i do{}while(0)

32 32 Typedef og noen ”Modifiers” Det er mulig å definere egne typer ved å bruke typedef Nye typer kan være helt nye typer som f.eks en struct, eller de kan være en alias for en annen standard type. Det er regnet som god praksis å bruke store bokstaver for en ny type definert med typedef: f.eks: typedef char* STRING; ”Auto” og ”Static”: Ved default blir en variabel i en funksjon definert som auto. C genererer autovariable når funksjonen blir kalt, og sletter dem igjen når funksjonen har returnert. Hvis man ønsker at en variabel definert i en funksjon ikke skal bli slettet, må den defineres som static. Dette må brukes hvis f.eks funksjonen returnerer en peker til en variabel definert inne i funksjonen. Variable som blir deklarert utenfor en funksjon blir definert som static ved default. En funksjon som defineres som static betyr noe helt annet. En static funksjon kan bare kalles i den filen hvor den er definert. En variabel definert som const, betyr at den ikke kan brukes på venstre-siden i en tilordning.

33 33 Enkel Makefile Gitt et system med to c-filer og en header fil: hellomake.c, hellofunc.c og hellofunc.h #include “c:/cpath/hellofunc.h" int main() { //Kall en funksjon fra en annen fil myPrintHelloMake(); return(0); } Program som kaller en funksjon fra c- filen hellofunc. Dette systemet kan enkelt kompileres med: En makefil er en fil som inneholder regler for hvordan systemet skal kompileres. Et program, som heter make, leser filen med navn “makefile” (default), og utfører de kompilerings-reglene som er definert i makefilen. Det vil si at hvis du har laget en makefil, kan du kompilere ved å kjøre make! Den enkleste makefilen som kan lages for dette systemet er: gcc hellomake.c hellofunc.c –o hellomake hellomake: hellomake.c hellofunc.c gcc hellomake.c hellofunc.c –o hellomake –I. Den første linjen inneholder alle filer programmet er avhengig av. Dette bruker make til bare å kompilere de filer som er endret siden sist. NB: make krever en tab før hver linje som den skal utføre.

34 34 Forts. Makefile CC=gcc CFLAGS=-I. hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o $(CFLAGS) Nå er kompilatoren og flaggene definert som makroer (konstanter). Ved å sette kompilatoren til å være avhengig av o-filene, så vet make at den må kompilere c- filene først, og så lenke filene etterpå. Denne typen makefil er bra nok for et lite prosjekt, men en ting mangler…, avhengigheten til h-filen! En litt mer kompilsert makefil: CC=gcc CFLAGS=-I. DEPS = hellomake.h %.o: %.c $(DEPS) $(CC) -c -o $< $(CFLAGS) hellomake: hellomake.o hellofunc.o gcc -o hellomake hellomake.o hellofunc.o -I. Makroen ($deps) inneholder all h-filene som c-filene avhenger av. Så lager vi en regel som sier at o-filene avhenger av c-filene og h-filene i $(deps), og at make skal generere o-filene som make trenger for å kompilere c-filene. –c flagget i gcc betyr kompiler men ikke link, –o betyr alle filene til venstre for :, og $< betyr den første filen i avh.-listen.

35 35 Dynamsk Minne-allokering Så langt har alle eksemplene allokert variable statisk ved å definere dem i programmet. Men hva om vi ønsker å allokere variable basert på dynamiske hendelser/input mens programmet kjøres? Dette krever dynamisk allokering. Funksjonen malloc(N) allokerer minne for N bytes calloc(N,k) allokerer minne for N elementer av en størrelse k. NB! Minne som allokeres dynamisk må senere frigjøres med funksjonen free()

36 36 Fallgruver med dynamisk minne Det er lett å glemme en peker til dynamisk minne som har blitt frigjort. Når man frigjør dynamisk minne, er det sikrest å slette alle pekere til det. Ved allokering av dynamisk minne, må man planlegge hvordan minnet senere skal bli frigjort. Allokert minne som man mister “kontakt” med kalles “memory leak”, og betyr at programmet “spiser” minne. Garbage collection Fordi dynamiske minne alltid bruker pekere, er det ingen måte for kompilatoren å sjekke at bruken av minnet er riktig, dette betyr at feil som kan detekteres med statisk allokering, ikke kan oppdages med dynamisk allokering.


Laste ned ppt "1 Krasjkurs i C (pluss litt matlab). 2 Innhold –Litt om Matlab –Funksjoner –Strukturer (Structs) –Noen matlab-funksjoner dere kan få bruk for – C –Kompilatorer."

Liknende presentasjoner


Annonser fra Google