380 likes | 630 Views
Formaterad utskrift printf(). %d utskrift av heltalsvariabel %x utskrift av heltalsvariabel men hexadecimalt %f utskrift av flyttalsvariabel <br> nyradstecken t tabulatortecken. För att använda printf() #include <stdio.h>. Inmatning med scanf(). int a; scanf( ”%d” , &a);.
E N D
Formaterad utskrift printf() %d utskrift av heltalsvariabel %x utskrift av heltalsvariabel men hexadecimalt %f utskrift av flyttalsvariabel \n nyradstecken \t tabulatortecken För att använda printf() #include <stdio.h> William Sandqvist william@kth.se
Inmatning med scanf() int a; scanf(”%d”, &a); Inmatning av ett heltal till variabeln a. Formatsträngen fungerar här på samma sätt som för printf(). Avsluta inmatningen med retur. Adressoperatorn&a betyder adressen till a. scanf() lägger det inmatade talet på a:s adress. (Dvs. i a). printf(”Variable a = %d at the hex address = %x\n”, a, &a); För att använda scanf() #include <stdio.h> William Sandqvist william@kth.se
Adressoperatorn & int b; Deklaration av heltalsvariabeln b. Plats reserveras. b = 18; Definition av variabeln b. Nu innehåller den talet 18. &b Adressoperatorn. Adressen till variabeln b. int * c; Deklaration av int-pekarvariabeln c. c = malloc( sizeof(int) ); Nu innehåller c en int-adress till en ledig plats. *c Avrefereringsoperatorn. Det som c pekar på. *c = 19; Talet 19 lagras på den plats som c pekar ut. free(c); Int-adressen ”lämnas tillbaka”. William Sandqvist william@kth.se
C:s minneskarta • Kod-segmentet innehåller programmets körbara kod • Data-segmentet innehåller variabler som är globala samt programkonstanter • Stack-segmentet innehåller Automatiska variabler. Funktionernas parametrar, returvärden och lokala variabler. • Heap-segmentet innehåller dynamiska variabler skapade under programkörningen. Begreppen Stack och Heap (två olika ”högar”) tillhör dataområdets allmänbildning! William Sandqvist william@kth.se
C:s minneskarta – var hamnar variabler? #include <stdio.h> int a = 17; int main(void) { int b = 18; int * c; c = malloc( sizeof( int ) ); *c = 19; printf("a = %d at address %x\n", a, &a); printf("b = %d at address %x\n", b, &b); printf("c = %d at address %x\n", *c, c); free(c); system("PAUSE"); return0; } Global variabel = Data segmentet Automatisk variabel = Stack Dynamisk variabel = Heap Återställ dynamiskt minne! William Sandqvist william@kth.se
Data-segmentet ”Globala” variabler, dvs variabler som deklarerats utanför programmets funktioner hamnar i datasegmentet. Initialiserade variabler förses med sina startvärden. Oinitialiserade variabler placeras för sig (.bss), de kan då enkelt åtminstone 0-ställas. I datasegmentet kan också konstanter och strängkonstanter lagras. Datasegmentet är statiskt, variablerna upptar plats under hela programkörningen både när de används och när de inte används. Nackdelen med de globala variablerna är att de kan nås från alla funktioner. De kan vara både parametrar och returvärden på en och samma gång för alla funktioner som använder dem – på ett oöverskådligt sätt – som gjort för problem! William Sandqvist william@kth.se
main()aktivitetspost Stacken När en funktion anropas så skapas en aktivitetspost på stacken. Den består av utrymme för funktionens parametrar och returvärde, samt de variabler som deklareras inuti funktionen ( = lokala variabler ). När en funktion avslutas så tas aktivitetsposten bort från stacken. Funktionen main() är speciell genom att den avslutas först när hela programmet kört klart. Dess aktivitetspost ligger kvar under programkörningen. William Sandqvist william@kth.se
funk2() Automatiska variabler main() anropar funktionen funk1(). En ny aktivitetspost skapas nu på stacken för den funktionens variabler. När funktionen kört klart returnerar den till main() och aktivitetposten tas bort. Nu anropas en annan funktion funk2(). Den funktionens aktivitetspost kan nu utnyttja samma minne på stacken. main()aktivitetspost Funktionernas variabler på stacken kallas för automatiskavariabler. Minnesutrymmet på stacken återanvänds av funktionerna och utnyttjas därmed effektivt. William Sandqvist william@kth.se
array[] funk3() array[] En funktion som genererar data Antag att funktionen funk2() genererar data och lagrar dessai en lokal array[] på stacken. Funktionen returnerar arrayens adress till main(), med hjälp av adressen kan main()nå ochanvända datat. Datat på stacken lever farligt! Om en ny funktion, funk3(), körs så skrivs datat över. Det behövs någon annan plats för datat. – Var skulle det kunna vara? William Sandqvist william@kth.se
array[] free() funk2() funk3() Heapen Funktionen funk2() behöver lagra sina data någon annanstans. Den kan anropa C:s funktion malloc() för att få utrymme på heapen. funk2() returnerar nu arrayens adress till main(). Datat finns fortfarande kvar om en ny funktion funk3() ska köra. Minnesutrymmet frigörs när man anropar funktionen free(). Om C:s minneshanterare är bra skriven utnyttjas minnesutrymmet på heapen effektivt. William Sandqvist william@kth.se
Hur stora är pekare? Det får man veta genom att köra ett testprogram på sin dator: #include <stdio.h> int main(void) { printf("typ\tbytes\n"); printf("char pekare \t%d\n", sizeof(char *)); printf("int pekare \t%d\n", sizeof(int *)); printf("float pekare \t%d\n", sizeof(float *)); printf("double pekare \t%d\n", sizeof(double *)); printf("void pekare \t%d\n", sizeof(void *)); system("PAUSE"); return0; } William Sandqvist william@kth.se
Vad är en void-pekare? char, int, float, double – pekare tar alla samma plats i minnet. Det som skiljer är hur stort adressteg som tas om man tex. ökar pekaren med 1. Den pekar då ut nästa av sin sort i minnet. En void-pekare är en reserverad minnesplats för en godtycklig pekarsort. Innan man använder pekaren måste den ”castas” (omvandlas) till önskad sort. Genom att använda void-pekare kan man skriva generella funktioner. Tex. kan funktionen Quicksort sortera ”vad som helst” genom att den är skriven för voidpekare. Typecast sker genom att man skriver den önskade data-typens namn i en parentes framför variabeln. float a; (int) a blir tillfälligt int (dvs bara heltals-delen kommer att räknas)! William Sandqvist william@kth.se
Endianess Datorminnen är Byteorienterade medan de flesta datatyperna består av flera Bytes. Antingen lagras den mest signifikanta Byten först (Big-endian) eller så lagras den minst signifikanta Byten först (Little-endian). Macintosh (Motorola), Sparc (Sun) … PC (Intel), VAX (Dec) … Bi-endian: Itanium (Intel)PA-RISC (HP) … William Sandqvist william@kth.se
J Swift endianess Termen ”endianess” kommer från Jonathan Swift’s Gullivers resor. De två kungadömena Lilleput och Blefuscu är i krig med varandra över en dispyt om vilken ända av frukostägget man ska knäcka! Lika välgrundade skäl ligger ofta bakom datateknikens olika ”standards” i vår tid … Internets överföringsstandard är big-endian som därför också kallas för Network order. (char*)&a adressen till a ändras från en ”int”-adress till en ”char”-adress. /* Endianess test */ #include <stdio.h> int main(void) { int a = 1; if( *( (char*)&a ) == 1) printf("Little Endian\n");else printf("Big Endian\n"); system("PAUSE"); return0; } William Sandqvist william@kth.se
Vi skall skicka 16 miljoner kronor över internet: 00000001 00000000 00000000 00000000 = 16.777.216 kr men om endianessen missförstås: 00000000 00000000 00000000 00000001 = 1 kr När har endianess betydelse? Endianessen har betydelse när två datorer kommunicerar med varandra, vid olika endianess måste en av datorerna kasta om Byte-ordningen ( vem är frivillig? ). Otur! William Sandqvist william@kth.se
Array ( vektor, matris ) #include <stdio.h> int main(void) { int temp1, temp2, temp3, temp4, temp5; printf("Ge temperatur --> "); scanf("%d",&temp1); printf("Ge temperatur --> "); scanf("%d",&temp2); printf("Ge temperatur --> "); scanf("%d",&temp3); printf("Ge temperatur --> "); scanf("%d",&temp4); printf("Ge temperatur --> "); scanf("%d",&temp5); printf("\ntemp 1 = %d", temp1); printf("\ntemp 2 = %d", temp2); printf("\ntemp 3 = %d", temp3); printf("\ntemp 4 = %d", temp5); printf("\ntemp 5 = %d\n", temp5); system("PAUSE"); return 0; } ett klumpigt program … William Sandqvist william@kth.se
Vi behöver indexerade variabler! #include <stdio.h> int main(void) { int temp[5]; int i; for(i=1 ; i<5 ; i++) { printf("Ge temperatur %d -->",i); scanf("%d",&temp[i-1]); } for (i=1 ; i<5 ; i++) printf(”\ntemp %d = %d",i, temp[i+1]); printf("\n"); system("PAUSE"); return 0; } En array deklareras! William Sandqvist william@kth.se
Beteckningar int temp[5]; Namnet på arrayen är samma sak som adressen till arrayen! Adress, konstant pekare Pekare, minnesutrymme som kan lagra adresser Minnesutrymme, variabel William Sandqvist william@kth.se
18 18 18 19 pekare * adress & och avreferering * Kort om C-språkets pekare int b; Deklaration av heltalsvariabeln b. Plats reserveras. b = 18; Definition av variabeln b. Nu innehåller den talet 18. &b Adressoperatorn. Adressen till variabeln b. int * c; Deklaration av int-pekarvariabeln c. c = &b; Nu pekar c på b. *c Avrefereringsoperatorn. Det som c pekar på. *c = 19; Talet 19 lagras på den plats som c pekar ut. Nu innehåller b = 19. ( ) ( ) ( ) William Sandqvist william@kth.se
Index- och pekarstegning for (i=0 ; i<5 ; i++) printf("%d\t%d\n",i, temp[i] ); Indexstegning: Pekarstegning: int * Pek = temp; for (i=0 ; i<5 ; i++) printf("%d\t%d\n",i ,*Pek++ ); Pekarstegning är i allmänhet snabbare – därför kommer kompilatorn att använda pekarstegning även om Du programmerar indexstegning! William Sandqvist william@kth.se
Strängar, char array En sträng är en char array som avslutats med strängslutstecknet ’\0’. ASCII nr 0. char str[]={’H’,’e’,’l’,’l’,’l’,’o’,’’,’w’,’o’,’r’,’l’,’d’,’!’,’\0’}; Eller mer ”rakt på sak”: char str[]=”Hello world!”; OBSERVERA! if(str1 == str2) betyder att str1 och str2 har samma adress, inte att strängarna har samma innehåll! Strängar jämförs i stället med funktionen strcmp(). William Sandqvist william@kth.se
Typecast av pekare Vi kan kopiera 16 bokstäver som 4 int – detta går snabbare (om datorn har 32 bitars buss). #include <stdio.h>int main(void){char text[16]="Hello my world!";char array[16];char * ptr1 = text;char * ptr2 = array;int i;for( i=0;i<4;i++) { *( ((int*)ptr2)++ ) = *( ((int*)ptr1)++ ); } printf("%s\n",array); system("PAUSE");return 0;} Pekarna typecastas till int*, och då ökar steget från en Byte till 4 Byte! William Sandqvist william@kth.se
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika slags minnen under ett "tak", ett variabelnamn • som t ex att en bank vill lagra fakta om konton • Kontonummer • Efternamn • Förnamn • Kontoställning • Adress • Postnummer William Sandqvist william@kth.se
struct typedefstruct {int number;char lastname[20];char firstname[20];int saldo;char adress[20];int zip; } konto; Från och med nu finns det en ny datatyp med namnet konto. Man kan deklarera variabler som konto. Delarna i variabeln når man med punktoperatorn ”.”. konto a; a.number = 125678; a.lastname = ”Sandqvist”; a.firstname = ”William”; Har man en pekare till structen når man i stället delarna med pilopera-torn ”->” konto * peka = &a; peka->number = 125678; William Sandqvist william@kth.se
struct array konto sthlm[5]; sthlm[3].zip = 16868; Här lagrar vi fem bankkonton. Vi går in i kontot 4 (index börjar på 0) och lägger dit postnumret. En array ligger i sammanhängande minne … S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-8 William Sandqvist william@kth.se
Sortera element i en array qsort() i stdlib.h Wikipedia Quicksort
Sorteringsfunktion Quick Sort Alla programmeringsspråk har inbyggda sorteringsfunktioner. C har funktionen qsort() som sorterar dataposterna i en array (eller structarray) i enlighet med en sorteringsordning som man själv specifierar. Exempel, en array med fem bokstäver: char alfa[5] = { ’C’, ’E’, ’A’, ’D’, ’F’, ’B’ }; qsort( (void*) alfa, 5, sizeof( char ), SorteringsOrdning ); Sorteras till: A, B, C, D, E, F om funktionen SorteringsOrdning() jämför alfabetiskt! Storlek på elementen i Bytes Funktionspekare, namnet på den sorteringsfunktion som skall användas Pekare till arrayen Antal element i arrayen William Sandqvist william@kth.se
Sorteringsfunktionen int Sorteringsordning( constvoid * a, constvoid * b){ if ( *((char *)a) < *((char *)b) ) return -1 ; else if ( *((char *)a) > *((char *)b) ) return 1 ; elsereturn 0 ; } QSORT arbetar med void-pekare, och kan därför användas till att sortera vad som helst i arrayer. Sorteringsfunktionen, som man skriver själv och som QSORT sedan använder, skall alltid returnera -1, +1, eller 0 om parameter b är före, efter, eller samma som parameter a. På så sätt kan man sortera arrayen efter valfri egenskap. Arrayer är således lätta att sortera! William Sandqvist william@kth.se
Länkad lista • En länkad lista är dynamisk. Det innebär att den enkelt kan öka och minska i storlek efter behov, till skillnad från till exempel en array, som har en fix storlek. I en länkad lista kan även element läggas till och tas bort i mitten. typedefstruct konto { int number;char lastname[20];char firstname[20];int saldo;char adress[20];int zip; struct konto* next; } konto ; S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-11 next är pekaren till nästa kontopost! William Sandqvist william@kth.se
Länkad lista i minnet En länkad lista lagras inte sammanhängande i minnet S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-10 Den här listan vill man inte gärna sortera! William Sandqvist william@kth.se
Länkad lista i C #include <stdio.h> typedef struct lista { char character; struct lista * next; } lista ; int main(void) { char c; lista * Ptr, * listPtr; /* Länkad lista med bokstäverna A B C D E byggs enklast bakifrån E D C B A */ listPtr = NULL; for(c='E';c >='A';c--) /* Räkna med bokstäver i for-loopen! */ { /* använd Heap-minne till listelementen */ Ptr = (lista *) malloc(sizeof( lista )); Ptr->next = listPtr; Ptr->character = c; listPtr = Ptr; } /* utskrift av listan */ Ptr = listPtr; do { printf("%c", Ptr->character); Ptr = Ptr->next; } while(Ptr != NULL); printf("\n"); system("PAUSE"); return 0; } Här borde man återlämnat Heap-minnet med free() – det fixar operativsystemet. William Sandqvist william@kth.se
Hur byter man plats på två element? • Skapa lista A B C D E • Byt plats på tredje och fjärde elementen (C,D): • c = (( listPtr->next)->next)->character; • (( listPtr->next)->next)->character = • ((( listPtr->next)->next)->next)->character; • ((( listPtr->next)->next)->next)->character = c; • Skriv ut listan: Länkade listor är svårare att sortera! William Sandqvist william@kth.se
Indexarray typedefstruct {int number;char lastname[20];char firstname[20];int saldo;char adress[20];int zip; } konto; konto * index[20]; S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-15 En indexarray innehåller pekare till posterna. Behöver man sortera posterna räcker det med att ”sortera” index, lika enkelt som att sortera en vanlig array. Ex. tredje postens saldo ska vara 100: index[2]->saldo = 100; William Sandqvist william@kth.se
Sortera index Man sorterar inte länkade listor. Däremot behöver man kunna sortera vilken ordning man vill bearbeta, eller skriva ut, posterna. Om man lagrar pekarna till posterna i en array (indexarray) så kan pekarna sorteras utan att posterna behöver flyttas i minnet. Sorteringsfunktionen använder pekarna med piloperatorn -> för att nå valfri delpost att sortera utifrån. William Sandqvist william@kth.se
Hur sorterar man elefanter? Genom att sortera pekarna – inte gärna genom att flytta på elefanterna!
Dubbellänkad lista • en dubbellänkad lista kan genomsökas lika effektivt i bägge riktningarna. • men nackdelen är att posterna innehåller två pekare som måste uppdateras. S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-13 William Sandqvist william@kth.se
Klasser och Objekt Objektorienterade programspråk, som tex, Java, använder klasser. En klass innehåller både data och (pekare till) de funktioner (metoder), som bearbetar data. Ett objekt är ett exemplar av klassen. Tex. klassen ”konton” har som objekt ”ett specifikt konto”. S Burd, Systems Architecture ISBN 0-619-21692-1 Figure 3-16 William Sandqvist william@kth.se