IN 147 Program og maskinvare

Like dokumenter
Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Dagens tema. Nyttige programmer Programmet make. Flyt-tall Representasjon av flyt-tall. Standarden IEEE 754. Systemkall i Unix

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Programmeringsspråket C Del 2

Dagens tema. Kort repetisjon om rutiner. Programmering i C Variable og adresser. Vektorer. Tekster. Preprosessoren. Separat kompilering

Dagens tema. Rutiner i LC-2 Og her er tilsvarende kode for LC-2: Funksjoner i C Her er det samme programmet i C: Kort repetisjon om rutiner

Del 4 Noen spesielle C-elementer

Dagens tema INF1070. Signaturer. Typekonvertering. Pekere og vektorer. struct-er. Definisjon av nye typenavn. Lister

Kapittel 1 En oversikt over C-språket

Programmeringsspråket C

Programmeringsspråket C Del 3

Del 1 En oversikt over C-programmering

Dagens tema INF1070. Vektorer (array er) Tekster (string er) Adresser og pekere. Dynamisk allokering

Dagens tema C, adresser og pekere

Nybegynnerkurs i C. Øyvind Grønnesby. 14. oktober Introduksjon Typer Operatorer Kontrollstrukturer Pekere Makroer Lenker

Programmeringsspråket C

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

Vektorer. Dagens tema. Deklarasjon. Bruk

Pekere og vektorer. Dagens tema. I C gjelder en litt uventet konvensjon:

Programmeringsspråket C

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

Oppgavene 1, 2, 4, 5, 6, 9, 12 og 13 passer best til å løses ved en datamaskin.

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema. Mer om C Enkle datatyper Sammensatte datatyper: Vektorer og matriser Tekster Mengder Strukturer Unioner Ringbuffere

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Dagens tema INF1070. Vektorer (array-er) Tekster (string-er) Adresser og pekere. Dynamisk allokering

Dagens tema. Dynamisk allokering Signaturer Definisjon av typer og nye typenavn Typekonvertering Pekere, vektorer og lister Dokumentasjon

Dagens tema. Oppsummering om assemblerspråk. Programmering i C. Bakgrunn. Et minimalt eksempel med forklaring. Datatyper i C.

Dagens program. Operativsystemer Prosesser og systemkall i UNIX Hente prosessens nummer Starte prosesser Vente på prosesser Utføre programmer

IN 147 Program og maskinvare. Vanlige feil ved bruk av pekere Feilsøking Debuggere

Plan: Parameter-overføring Alias Typer (Ghezzi&Jazayeri kap.3 frem til 3.3.1) IN 211 Programmeringsspråk

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Oversikt. INF1000 Uke 2. Repetisjon - Program. Repetisjon - Introduksjon

Programmering i C++ Løsningsforslag Eksamen høsten 2005

IN 147 Program og maskinvare

INF1000 undervisningen INF 1000 høsten 2011 Uke september

En oppsummering (og litt som står igjen)

HØYSKOLEN I OSLO, AVDELING FOR INGENIØRUTDANNING

Kort om meg. INF1000 Uke 2. Oversikt. Repetisjon - Introduksjon

2 Om statiske variable/konstanter og statiske metoder.

Den siste dagen. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Veien videre... Eksamen

Velkommen til INF2100 Jeg er Dag Langmyhr

Dagens tema: 12 gode råd for en kompilatorskriver

Bakgrunnen for INF2100. Velkommen til INF2100. Prosjektet. Hva gjør en kompilator?

Runtime-omgivelser Kap 7 - II

Tema for siste forelesning:

Pensum Hovedtanker Selvmodifiserende Overflyt Veien videre Eksamen. Oppsummering

Runtimesystemer - II. Parameteroverføring Call by value Call by reference Call by value-result Call by name INF 3110/ INF

Oversikt. INF1000 Uke 1 time 2. Repetisjon - Introduksjon. Repetisjon - Program

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Oppgave 1 JK-flip-flop (Total vekt 20%)

Dagens tema Kapittel 8: Objekter og klasser

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

2 Om statiske variable/konstanter og statiske metoder.

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

Transkript:

Dagens tema Mer om C Cs preprosessor Allokering av variable Separat kompilering Programmet make Pekere i C Operasjoner på pekere Pekere og vektorer Referanseparametre Pekere til «alt» og «ingenting» Dynamisk allokering Ark 1 av 24 Forelesning 24.2.1998

Cs preprosessor Før selve kompileringen går C-kompilatoren gjennom koden med en preprosessor (som er programmet /usr/lib/cpp). Dette er en programmerbar tekstbehandler som gjør følgende: Henter inn filer #include "incl.h" #include <stdio.h> Hvis filen er angitt med spisse klammer (som for eksempel <stdio.h>), hentes filen fra området /usr/include. Ellers benyttes vanlig UNIX-notasjon for filer. Forelesning 24.2.1998 Ark 2 av 24

Leser makro-definisjoner og ekspanderer disse i teksten: #define ATARI_ST #define N 100 #define MIN(x,y) ((x)<(y)? (x) : (y)) Av gammel tradisjon gis makroer navn med store bokstaver. Benytter man makroer med parametre, bør disse settes i parenteser. Likeledes, hvis definisjonen er et uttrykk med flere symboler, bør det stå parenteser rundt hele uttrykket. Betinget kompilering. Her angis hvilke linjer som skal tas med i kompileringen og hvilke som skal utelates. Forelesning 24.2.1998 Ark 3 av 24

Betinget kompilering Følgende direktiver finnes for betinget kompilering: #if Hvis uttrykket etterpå er noe annet enn 0, tas etterfølgende linjer tas med. Uttrykket kan ikke inneholde variable eller funksjoner. #ifdef Hvis symbolet er definert (med en #define), skal etterfølgende linjer tas med. #ifndef Motsatt av #ifdef. #else Skille mellom det som skal tas med og det som ikke skal tas med. #endif Slutt med betinget kompilering. Eksempel: #define ATARI_ST #ifdef ATARI_ST int x; #else long x; #endif Forelesning 24.2.1998 Ark 4 av 24

Det er også mulig å styre betinget kompilering gjennom gcc-kommandoen: gcc -ansi -c -DATARI_ST gir samme effekt som om det sto #define ATARI_ST i program-koden. På denne måten er det mulig å ha flere versjoner av koden (for eksempel for flere maskin-typer) og så kontrollere dette utelukkende gjennom kompileringen. Fare med betinget kompilering Man kan risikere å ha kode som aldri har vært kompilert, og som kan inneholde de merkeligste feil. Forelesning 24.2.1998 Ark 5 av 24

Allokering av variable I C kan man angi hvordan (og til dels hvor) variable skal allokeres. Mulighetene er: Automatic er lokale variable i funksjoner. Variablene oppstår når funksjonen kalles, og de resirkuleres når funksjonen er ferdig. En initiering foretas hver gang variabelen oppstår. Kun enkle variable kan initieres. static er variable som oppstår når programmet lastes opp for kjøring. De ligger alltid på samme sted, og hvis de er lokale til en funksjon, vil de bevare verdien fra ett kall til det neste. En eventuell initiering foretas altså kun én gang. NB! static-spesifikasjonen har en annen sideeffekt når den benyttes på globale deklarasjoner (både variable og funksjoner): Navnet på deklarasjonen blir ukjent utenfor filen. Forelesning 24.2.1998 Ark 6 av 24

extern indikerer at variabelen eller funksjonen er deklarert et annet sted. Bindingen til denne andre variabelen skjer under linkingen. register indikerer at variabelen bør ligge i et register. På denne måten kan man hjelpe kompilatoren til å lage mer effektiv kode. gcc ignorerer slike tips. Vi kan lage følgende tabell: automatic static extern register Globale variable S/OK OK Globale funksjoner OK OK Parametre S OK Lokale variable S OK OK OK Lokale funksjoner OK Her angir S at spesifikasjonen er standard, men OK angir at det er et valgbart alternativ. Forelesning 24.2.1998 Ark 7 av 24

Separat kompilering I utgangspunktet er det ingen problem med separat-kompilering i C; hver fil utgjør en enhet som kan kompileres for seg selv, uavhengig av alle andre filer i programmet. gcc -ansi -c del.c vil kompilere filen del.c og lage del.o som inneholder den kompilerte koden. Imidlertid er det en fare for at strukturer, makroer, typer og andre elementer ikke blir skrevet likt i hver fil. Dette løses ved hjelp av definisjonsfiler («header files»), hvis navn gjerne slutter med.h. Filen incl.h: #define N 100 typedef char *string; Forelesning 24.2.1998 Ark 8 av 24

Filen prog.c: #include "incl.h" int main(void) { string s[n];. } Definisjonsfiler inneholder gjerne følgende: Makrodefinisjoner (#define) Typedefinisjoner (typedef, union, struct) Eksterne spesifikasjoner (extern) Funksjonssignaturer (extern int f(int,char);) (Legg merke til semikolonet sist!) Forelesning 24.2.1998 Ark 9 av 24

Programmet make Det er mange praktiske problemer forbundet med programmering av et større program: Hvordan holde orden på et stort program når det er mange separatkompilerte filer? Hvis én fil endres, hvilke filer må da kompileres på nytt? Hvordan sikre at alle de riktige opsjonene er med ved hver kompilering? Hvordan unngå at brukeren skriver seg i hjel på lange kommandolinjer? Løsningen er make! Forelesning 24.2.1998 Ark 10 av 24

Brukeren lager en fil med navn makefile eller Makefile. Den ser slik ut: F 0 : F 1 F 2... F n Tab Kommandolinje Tab Kommandolinje. Dette betyr: 1. Filen F 0 er «avhengig» av filene F 1, F 2,..., F n. Det betyr at hvis F 0 er eldre enn noen av disse, må F 0 rekompileres. 2. Kommandolinjene må da utføres for å rekompilere F 0. Disse linjene må starte med en Tab. Forelesning 24.2.1998 Ark 11 av 24

Programmet make gjør altså følgende: 1. Først leses filen makefile eller Makefile. 2. Så bygger make opp en oversikt (nærmere bestemt en graf) over hvilke filer som avhenger av hvilke. Utgangspunktet (roten) for denne grafen oppgis som parameter til make; ellers tas første fil. Denne grafen angir hvilken rekkefølge filene skal sjekkes (og eventuelt rekompileres) i. For C-programmer spiller ikke dette noen rolle, men for noen språk (f.eks. Simula) er dette vesentlig. 3. Nå kan hver fil sjekkes i riktig rekkefølge. Hvis (a) filen ikke finnes, eller (b) noen av filene den er avhengig av ikke finnes, eller (c) filen er eldre enn noen av de den er avhengig av, blir den rekompilert. Brukeren får beskjed om hvilke kommandoer som utføres. Forelesning 24.2.1998 Ark 12 av 24

Et eksempel: incl.h: #define N 100 func.c: #include "incl.h" int N2(void) { return 2*N; } prog.c: #include <stdio.h> #include "incl.h" extern int N2(void); int main(void) { if (N2() == 2*N) printf("n2 er OK.\n"); else printf("n2 er feil!\n"); } Dette fordrer følgende makefile: prog: prog.o func.o gcc -ansi prog.o func.o -o prog prog.o: prog.c incl.h gcc -ansi -c prog.c func.o: func.c incl.h gcc -ansi -c func.c Forelesning 24.2.1998 Ark 13 av 24

Nå kan dette prøves: $ make gcc -ansi -c prog.c gcc -ansi -c func.c gcc -ansi prog.o func.o -o prog $ prog N2 er OK. $ touch prog.c $ make gcc -ansi -c prog.c gcc -ansi prog.o func.o -o prog $ touch incl.h $ make gcc -ansi -c prog.c gcc -ansi -c func.c gcc -ansi prog.o func.o -o prog $ prog N2 er OK. $ make make: prog is up to date $ Forelesning 24.2.1998 Ark 14 av 24

Det er mulig å definere forkortelser (makroer uten parametre): CC = gcc CFLAGS = -ansi -O -DATARI_ST -DIFI BIN = func.o prog.o prog: $(BIN) $(CC) $(CFLAGS) $(BIN) -o prog prog.o: prog.c incl.h $(CC) $(CFLAGS) -c prog.c func.o: func.c incl.h $(CC) $(CFLAGS) -c func.c Forelesning 24.2.1998 Ark 15 av 24

Pekere Deklarasjon Deklarasjon i C: long *p, *q; Operatorer i C Det finnes kun tre pekeroperatorer i C: &x Gir en peker til x *p Gir det p peker på p->s Det samme som (*p).s Forelesning 24.2.1998 Ark 16 av 24

Bruk av pekere i C int a = 1; /* a inneholder 1 */ int b = 2; /* b inneholder 2 */ int *p1 = &a; /* p1 peker nå på a. Effekten er den samme som om det hadde stått: int *p1; p1 = &a; */ int *p2 = p1; /* p2 peker også på a */ *p2 = 4; /* Nå inneholder a verdien 4 */ p2 = &b; /* Nå peker p2 på b */ *p1 = *p2; /* Nå inneholder a (som p1 peker på) verdien 2 (som kom fra b) */ Forelesning 24.2.1998 Ark 17 av 24

Pekere og vektorer I C er pekere og vektorer to sider av samme sak, siden følgende alltid gjelder: a[i] *(a+i) Dessuten vil en referanse til en vektor alltid gi adressen til den første element: Følgende er altså lov: a &a[0] int arr[100], i = 0, *ip; ip = arr; /* alternativt ip = &arr[0]; */ while (i < 100) { printf("%10d", *ip); ip++; i++; } Forelesning 24.2.1998 Ark 18 av 24

Siden navnet på en vektor egentlig er en peker til første element, parameteroverføres alle vektorer som pekere. Funksjoner kan derfor skrives på to ulike måter: int strlen(unsigned char s[]) { int ix = 0; } while (s[ix]!= \0 ) ix++; return ix; int strlen(unsigned char *s) { int num = 0; } while (*s!= \0 ) { num++; s++; } return num; Kallet på funksjonen blir det samme, så brukeren av funksjonen trenger ikke vite hvorledes den er implementert. Versjoner med pekere er imidlertid nesten alltid raskest. Forelesning 24.2.1998 Ark 19 av 24

Referanseparametre i C Simula: procedure ModMany(X, M1, M2, M3, M4); name M1, M2, M3, M4; integer X, M1, M2, M3, M4; begin M1 := Mod(X,2); M2 := Mod(X,3); M3 := Mod(X,5); M4 := Mod(X,7); end; C: void modmany(int x, int *m1, int *m2, int *m3, int *m4) { *m1 = x%2; *m2 = x%3; *m3 = x%5; *m4 = x%7; } Kall: Simula: ModMany(a, v1,v2,v3,v4); C: modmany(a, &v1,&v2,&v3,&v4); Forelesning 24.2.1998 Ark 20 av 24

Implementasjon av pekere Pekere implementeres ganske enkelt ved å lagre adressen til objektet. På MIPS opptar alltid en peker 32 bit (det samme som en int eller en long). Dette kan være anderledes på andre maskiner. Pekere til alt Det er ikke gitt at alle pekere tar like stor plass. Deklarasjonen void * er en peker som er garantert stor nok. Forelesning 24.2.1998 Ark 21 av 24

Peker til ingenting I f.eks. stdio.h: #define NULL 0 Verdien 0 er fast i C. Man kan altså skrive if (P!= NULL)... if (P)... Ved tilordning bør man alltid typekonvertere: int *p; p = (int*)null; f(p, (int*)null); Forelesning 24.2.1998 Ark 22 av 24

Addisjon og subtraksjon av pekere Addisjon og subtraksjon arter seg litt spesielt: xxx *p; p + n betyr «det n-te elementet etter p». Eksempler: char *pc = (char*) 0x1000; short *ps = (short*) 0x1000; long *pl = (long*) 0x1000; pc = pc+1; /* Nå er pc == 0x1001. */ pc += 2; /* pc == 0x1003. */ ps = ps+1; /* Nå er ps == 0x1002. */ ps += 2; /* ps == 0x1006. */ pl++; /* Nå er pl == 0x1004. */ pl += 2; /* pl == 0x100C. */ Det tilsvarende gjelder for subtraksjon. Forelesning 24.2.1998 Ark 23 av 24

Dynamisk allokering «Nye» data-områder allokeres med funksjonen malloc, som finnes i stdlib.h. Plass til 200 heltall (long): #include <stdlib.h> long *p;. p = (long *)malloc(200*sizeof(long)); Frigivelse free(p); Det er ingen automatisk frigivelse, som i f.eks. Simula. Forelesning 24.2.1998 Ark 24 av 24