Del 4 Noen spesielle C-elementer 1 RR 2016
Header-filer inneholder Prototypene til funksjonene i standard biblioteket Verdier og definisjoner som disse funksjonene bruker #include <stdio.h> #include <string.h> sørger for kompilatoren tar med prototypene til biblioteksfunksjonene. 2
const spesifikasjonen. En variabel som vi deklarerer som const kan ikke endre sin verdi. Benyttes for å lage konstanter. Ex: const float pi = 3.1415; pi = 3.15; // Ikke lov å endre verdien på en konstant. 3
Preprosessor direktiver. I C kan vi benytte noen preprosessor direktiver som blir utført før selve programmet blir kompilert. Vi har tidligere benyttet; #include (For å inkludere filer før kompilering). Et annet direktiv er #define. #define benyttes for å angi at en tekst skal byttes ut gjennom hele programmet. #define ANTALL 100 #define PI 3.1415 4
volatile Benyttes for å fortelle at en variabel kan bli forandret av faktorer på utsiden av programmet (f.eks av operativsystemet, interrtupt, timere). Kompilatoren vil da ta hensyn til dette for angitt variabel, og unngår dermed å optimalisere koden til denne variabelen. Benyttes i interrupt og timer rutiner. Ex; volatile int clock; /* clock kan bli oppdatert av op.sys etc */ 5
static Lokale variabler blir slettet når en funksjon avsluttes. I en del sammenhenger ønsker vi at de lokale variablene skal være faste, slik at verdien til variablene huskes gjennom hele programmet. Vi kan benytte globale variabler for å oppnå en slik effekt, men globale variabler kan også gi dårlig sikkerhet. I C kan vi lage faste lokale variabler. Benytter da static spesifikatoren. void inkrement() { int tall1=1; static int tall2=1; // lokal variabel // lokal variabel med fast plass i minnet. 6
Register spesifikatoren Hvis vi spesifiserer at en variabel skal være register betyr det at datamaskinen skal lagre variabelen på en slik måte at den raskest mulig kan benyttes, dvs i CPU ens registre og ikke i RAM. Variabler som benyttes ofte, slik som løkketellere vil kunne gi tidsbesparelser hvis de legges som register variabler. Eksempel; register int teller1, teller2; 7
Kortform tilordnings operatorer. Kan benytte følgende operatorer ved tilordning; = += -= *= /= %= a += b; a -= b; a *= b; a /= b; a %= b; a = a+b; a = a-b; a = a*b; a = a/b; a = a%b; 8
Multiple tilordninger. I C er det enkelt å tilordne den samme verdien til mange variabler; teller = inkr = indeks = 10; Først tilordnes indeks til 10, deretter tilordnes inkr til indeks (10), og til slutt settes teller lik inkr (10). 9
Bit operatorene. I C finnes det 6 operatorer for bitmanipulering. Med disse operatorene kan vi jobbe mot de enkelte bit som en heltallsverdi består av. I C finnes følgende bit-operatorer; & x&y bitvis og x y bitvis eller ^ x^y bitvis eksklusiv eller x enerkompliment << x<<y x skiftet y bits til venstre >> x>>y x skiftet y bits til høyere 10
Eksempel med & operatoren. Bitvis og operator. & Operander 9430 5722 Binær representasjon 00100100 11010110 00010110 01011010 9430 & 5722 00000100 01010010 11
? : operatoren. Operatoren? : erstatter en if else setning. Generell form;. (betingelse)? uttrykk1 : uttrykk 2; Hvis betingelsen er sann er resultatet uttrykk1 ellers uttrykk2. (x < 0)? a= 20 : a = 100; res = (i > 0 )? 5 : 0; 12
Break, continue og goto break kan benyttes i løkker. Medfører umiddelbar uthopp av løkka til setningen som følger deretter. continue tvinger en løkke til å starte på toppen igjen, slik at etterfølgende setninger blir hoppet over. goto ubetinget hopp til en valgt plass i kode (label). Lite benyttet. 13
extern og auto extern benyttes for å fortelle at en global variabel allerede er definert et annet sted i programmet. Benyttes når globale verdier skal benyttes av flere C-filer. auto benyttes for å fortelle at en variabel skal oppføre seg som en lokal variabel. Ettersom dette er standard så er auto unødvendig. 14
typedef I C kan vi definere egne navn på eksisterende datatyper. typedef benyttes til dette. (Lite benyttet). typedef float desimaltall; typedef int my_int; desimaltall lengde; my_int teller; 15
enum enum benyttes for å lage en liste av symbolske heltallskonstanter. enum ukedag{ma, TI, ON, TO, FR, LO, SO}; ukedag er nå navnet på den nye datatypen. De symbolske oppramsingene inne i parentesen får fortløpende verdi fra 0 og oppover. Det vil si at MA == 0, TI == 1, ON == 2, osv Vi kan nå lage en variabel av type dager; enum ukedag dag; dag = MA; // dag får verdien 0 dag = FR; // dag får verdien 4. 16
sizeof operatoren. Gir oss antall bytes en datatype består av. Er nyttig når vi skal avsette plass i minne og på filer. int main(void) { char ch; int i; int tab[4]; printf( %d\n, sizeof ch); printf( %d\n, sizeof i); printf( %d\n, sizeof (float)); printf( %d\n, sizeof (double)); printf( %d\n, sizeof tab); return 0; } 17
cast operatoren Lar oss midlertidig omgjøre en datatype til en annen. Nyttig når en har behov for å gjøre float om til int, int til float osv. (type) verdi; Ex: float f=12.34;... printf( %d\n, (int) f);... 18
Strukturer 1. En struktur er en datatype vi selv kan lage for å holde data/informasjon, som er knyttet til hverandre på en oversiktlig (strukturert) måte. Vi kan opprette egne datatyper etter behov, og benytte et navn for å få tilgang til en samling av data. struct person { }; char navn[41]; int alder; char telefon[15]; struct person stud1, stud2, stud3; struct person studdata[100]; stud1.alder = 22; 19
Strukturer 2. struct person{ char navn[41]; int alder; char telefon[15]; } stud1, *studpkr; studpkr = &stud1; studpkr->alder = 23; NB!! Bruk dot-operatoren får å få tilgang til et strukturmedlem. Bruk pil-operatoren for å få tilgang til et strukturmedlem når det benyttes pekere. 20
Reservering av dynamisk minne (1). Vanlig variabler blir enten lagt statisk i minne (globale variabler) eller på en stakk (lokale variabler). Noen ganger vil det ofte være behov for å legge data midlertidig i minne. Det kan være vanlige variabler, tabeller og strukturer (objekter). Mye benyttet når vi lager datastrukturer som lenkede lister, binære trær etc der vi ikke vet antall elementer på forhånd, og avsetter plass etter behov. Vi kan reservere minne (et antall bytes) når vi trenger det med funksjonen; void *malloc( size_t num_bytes); Funksjonen returnerer en peker til starten av minneblokken vi har reservert. 21
Reservering av dynamisk minne (2). Minnet frigjøres med; void free( void *ptr); ptr er en peker til starten av reservert minne. int main(void) { int i; double *pkr;... pkr = malloc(100*sizeof(double)); // 400 bytes... // Kan nå benytte reservert minne... free(pkr);... 22
Betingelse-styrt kompilering (1) Med preprosessor kommandoer kan vi styre hvordan C koden vår skal kompileres. Vi kan angi at kun visse deler skal tas med, og vi kan sjekke om include filer allerede er inkludert. Følgende direktiver kan benyttes. #if #else #elif #endif #ifdef #ifndef 23
Betingelse-styrt kompilering (2) #include <stdio.h> #define DEBUG #define TEST 3 int main(void) { #ifdef DEBUG printf("debug er definert!!! \n");... #else printf("debug er ikke definert!!! \n");... #endif... #undef DEBUG... 24