Poster ( structar ) Postdeklarationer



Relevanta dokument
Funktionspekare, inledning: funktionsanropsmekanismen. Anrop via pekare

Tentamen *:58/ID100V Programmering i C Exempel 3

2 Pekare och dynamiska variabler.

Övning från förra gången: readword

#include <stdio.h> #include <string.h>

*Pekarvärden *Pekarvariabler & *

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Det finns många flaggor till g++,

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Introduktion C-programmering

Dynamiskt minne. Vad är dynamiskt minne Motivering Hur gör man i C Övningar

Pekare och arrayer. Indexering och avreferering

Programmeringsteknik med C och Matlab

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Repetition C-programmering

Innehåll. Pekare Exempel

Programsystemkonstruktion med C++: Övning 1. Karl Palmskog september 2010

Innehåll. Pekare Exempel

TDIU01 - Programmering i C++, grundkurs

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Föreläsning 10. Pekare (Pointers)

Att använda pekare i. C-kod

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Strängar. Strängar (forts.)

TDIU01 - Programmering i C++, grundkurs

Programmering av inbyggda system. Pekare och Arrayer. Viktor Kämpe

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

TDDC76 - Programmering och Datastrukturer

Minnestilldelning (allokering) och frigörande (avallokering) av minne

C-programmering, föreläsning 2 Jesper Wilhelmsson

Enkla datatyper minne

Övning 3 i 2D1324. Strukturering h filer deklaration vs definition Debuggning gdb Preprocessorn #define assert(s) FILE LINE Länkning

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Lösningar till uppgifterna sätts ut på kurssidan på nätet i dag kl Omtentamen i Programmering C, Fri, Kväll,

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

C++-programmets beståndsdelar

Byggstenar. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Grundläggande datatyper

Värmedistribution i plåt

Ett enkelt program i C++, hello.cpp. #include <iostream> int main() { std::cout << "Hello World\n"; return 0; } C++, Övning 1

struct egendefinierad typ struct LECTURE_TYPE { char teacher[99]; float lengthinminutes; char type; /* L = lecture, E = exercise */ };

Vad händer när man kör ett program? Program och processer. Funktionsanrop. Avsluta programmet

grundläggande C++, funktioner m.m.

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

IS1200 Datorteknik. Övning CE_O4 Maskinnära programmering med C Förberedelser till hemlaboration 1

GPT föreläsning 8. Förra veckan: Man kan ta tiden på en sorterad teckensträng Förra gången: Problemlösning på lägre nivå kan sortera funktioner

Föreläsning 12. struct

Tentamen i Programmering grundkurs och Programmering C

Objektorienterad programmering

6.1 Kompilering och lite grundläggande information

Programmeringsteknik för Ingenjörer VT06. Föreläsning 10

Programmeringsteknik med C och Matlab

Länkade listor kan ingå som en del av språket, dock ej i C Länkade listor är ett alternativ till:

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Tentamen i. för D1 m fl, även distanskursen. lördag 19 januari 2013

Föreläsning 9. struct

prog: prog.c gcc -g -Wall prog.c /usr/local/bib/c/58an/modules/modul.o -o prog

Funktionens deklaration

Skizz till en enkel databas

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Föreläsning 5: Introduktion av pekare

Tentamen i Programmering grundkurs och Programmering C

2D1387, Programsystemkonstruktion med C++ Johnny Bigert, Kursens hemsida:

Kapitel 1. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Kapitel 1 grunderna i C++

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

4 Sammansatta datatyper

C-programmering, föreläsning 1 Jesper Wilhelmsson

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

Dagens föreläsning. Specialtecken. Mer om printf. Formateringssträngar. Mer om scanf. Programmeringsteknik för Ingenjörer VT05

Programmering i C. Vad är C? Målsättning. Litteratur. Jämförelse med Java. Exempel : Ett program som skriver ut texten Hello, world

Pekare. Pekare. Varför använder vi pekare? Vad är en pekare? Pekare. Deklaration/initiering av pekare

Programmering av inbyggda system. Pekare och Arrayer. Ulf Assarsson. Originalslides av Viktor Kämpe

Assemblerprogrammering, ARM-Cortex M4 del 3

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Översikt Introduktion DST 1. Nicholas Wickström. IDE, Högskolan i Halmstad. N. Wickström

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Klassdeklaration. Metoddeklaration. Parameteröverföring

Tentamen i. Programmering i språket C

C++ Funktioner 1. int summa( int a, int b) //funktionshuvud { return a+b; //funktionskropp } Värmdö Gymnasium Programmering B ++ Datainstitutionen

Tentamen i Programmering grundkurs och Programmering C

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

1 Modulär programutveckling.

F5: Högnivåprogrammering

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Programmering: att instruera en maskin att utföra en uppgift, kräver olika språk:

F5: Högnivåprogrammering

En klass behöver både deklaration och definition. Daniel Aarno Globala funktioner och variabler är OK.

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

TDIU01 - Programmering i C++, grundkurs

Tommy Färnqvist, IDA, Linköpings universitet

Tentamen i Programmering grundkurs och Programmering C

Innehåll. EDAf30: Programmering i C++, 7.5 hp. EDAf30: Programmering i C++, 7.5 hp Viktiga skillnader mot Java

TDDC76 - Programmering och Datastrukturer

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

TDP004. Minne och pekare. Eric Elfving Institutionen för datavetenskap

4. Maskinnära programmering i C. Förberedelser till hemlaboration 1.

... Funktionsanrop. Vad händer när man kör ett program?

Programmering i C++ EDA623 Mer om klasser. EDA623 (Föreläsning 6) HT / 26

En kort text om programmering i C.

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

Transkript:

Poster ( structar ) Exempel på en postdeklaration: struct person { int id; char namn[20]; int vikt, skonr; p1, p2; Detta definierar två variabler p1 och p2 som poster med termerna id, namn, vikt och skonr. C:s term för term är dock medlem (member). Obs! att till skillnad från Java skapas utrymmen för posterna där definitionen finns, ett statiskt eller lokalt utrymme poster behöver inte skapas dynamiskt. Obs! vidare att man inte i typdefinitionen kan ange hur medlemmar ska initieras. Medlemsåtkomst görs med operatorn. (punkt): p1.id=13; strcpy(p1.namn, Jozef ); p1.vikt=62; p1.skonr=47; För medlemsåtkomst via pekare till posten finns även operatorn ->, mer om detta senare. Bild 48 Postdeklarationer Ordet person i deklarationen ovan kallas structure tag. Kombinationen struct person kan användas som typnamn för denna posttyp i senare deklarationer: struct person p3; struct person folk[10]; struct person *perspek; void f1(struct person p); struct person f2(void); struct person *f2(void); - ännu en variabel - array med 10 poster - pekare till en personpost - funktion med ett personpostargument - funktion som returnerar personpost - funktion som returnerar pekare till personpost Bild 49 1

Postdeklarationer (forts.) Structure tag kan utelämnas vid postdeklarationen, men då kan man inte deklarera fler variabler av denna typ eller ange denna typ för ett funktionsargument. Variabelnamn kan också utelämnas: struct person { int id; char namn[20]; int vikt, skonr; ; varvid hela deklarationen blir endast en typdefinition. Variabler kan sedan deklareras med typen struct person. Obs! semikolon efter högerklammern! Annars kommer orden fram till nästa semikolon att uppfattas som deklarationer av variabler av denna typ (speciellt förvirrande om felet med utelämnat semikolon finns i en headerfil man har inkluderat). Däremot får det ju inte finnas semikolon efter högerklammern som används som avslutning på en funktionsdefinition eller en sammansatt sats. Postdeklarationer kan förenklas med typnamndefinitioner (typedef), mer om detta senare. Bild 50 Initiering, tilldelning mm Postvariabler kan initieras vid definition: struct person p1={13, Jozef, 62, 47; struct person folk[3]={{13, Jozef, 62, 47, {17, Stefan, 98, 39, {23, Åsa, 51, 36; I ANSI-C89 måste alla initieringsvärden vara konstanta uttryck. Poster kan även tilldelas, varvid hela poster kopieras: folk[0]=p1; Postkonstanter kan dock endast användas vid initiering. Bild 51 2

Poster som argument Liksom alla andra datatyper utom arrayer har poster värdesemantik som argument till funktioner eller som returvärden från funktioner. Det innebär att när man skickar en post som argument till en funktion så kopieras hela postinnehållet till ett lokalt utrymme för det formella argumentet (värdeanrop). void skriv(struct person p){ printf( %d %s %d %d\n, p.id, p.namn, p.vikt, p.skonr); void funk(void){ struct person jag={13, Jozef, 62, 47; skriv(jag);... Eventuella förändringar inuti den anropade funktionen görs i den lokala kopian och fortplantar sig inte till det aktuella argumentet. skriv jag 13 Jozef 62 47 p 13 Jozef 62 47 Bild 52 Ändringsbara postargument Vill man kunna ändra i det aktuella postargumentet måste funktionen ta emot en pekare till posten och adressen till postvariabeln måste skickas vid anropet: void banta(struct person *p){ (*p).vikt--; void funk(void){ struct person jag={13, Jozef, 62, 47; banta(&jag);... banta jag p 13 Jozef 62 47 Bild 53 3

Poster som returvärden Poster kan även returneras av funktioner, varvid en kopia av postinnehållet returneras: struct person lasperson(void){ struct person p; printf( Ange id och namn: ); scanf( %d %20s, &p.nr, &p.namn); while(getchar()!= \n ) ; p.vikt = 0; p.skonr = 0; return p; void funk(void) { struct person p1; p1=lasperson();... lasperon() ovan returnerar en kopia av den lokala variabeln, som kopieras in i mottagande variabeln. Bild 54 En fälla (gör inte så!) Funktionen lasperson i tidigare exempel liknar denna felaktiga konstruktion: struct person *lasperson(void){ /* OBS! Fel! */ struct person p; printf( Ange id och namn: ); scanf( %d %20s, &p.nr, &p.namn); while(getchar()!= \n ) ; p.vikt = 0; p.skonr = 0; return &p; Returnerar pekare till lokalt utrymme! Denna funktion returnerar en pekare till ett lokalt utrymme. När funktionen är klar kommer detta utrymme att städas bort från stacken för att användas för nästa funktionsanrop, men den som tagit emot pekaren kommer ju att tro att den pekar på postutrymmet. Däremot skulle det vara en korrekt konstruktion om struct person p hade varit deklarerad som static. Bild 55 4

Ett trick Om man vill ha posters värdesemantik för arrayer (i någon speciell situation) så kan man bygga in arrayen i en post: struct mystring { char str[256]; ; Variabler av typen struct mystring kommer att bara bestå av arrayen str, men kommer att få värdesemantik som argument och returvärden. struct mystring m1 = {{ Jozef, m2; m2 = m1; printf( %s\n, m2.str); Obs! dock att varje variabel av typen struct mystring kommer att innehålla en hel array på 256 bytes. Bild 56 Medlemsåtkomst via pekare till post Om man vill komma åt medlemmar i en post som pekas ut av en pekare, t.ex.: struct person p1={13, Jozef, 62, 47; struct person *perpek=&p1; så skall pekaren avrefereras och medlemsåtkomsten göras med.-operatorn. Denna operator har dock högre prioritet än *, varför parenteser måste användas: (*perspek).id=17; Detta är för jobbigt att skriva för en C-programmerare, så man har infört en till operator -> som har precis denna betydelse: perspek->id=17; Denna operator kan givetvis även användas i funktioner som tar emot pekare till poster för att kunna ändra i posterna: void banta(struct person *p){ p->vikt--; Bild 57 5

Dynamisk minnesallokering Dynamisk minnesallokering görs med hjälp av funktioner vilkas prototyper finns i biblioteket stdlib, dvs. görs tillgängliga genom: #include <stdlib.h> Det finns fyra sådana funktioner (typen size_t nedan är någon för aktuell plattform lämplig heltalstyp, definierad i standardheaderfilerna): void *malloc(size_t size); Allokerar ett utrymme av storleken size bytes, returnerar en pekare till utrymmet eller NULL om det inte fanns något mer utrymme. Motsvarar Pascals och Javas New. void *calloc(size_t number, size_t size); Allokerar ett sammanhängande utrymme för number stycken objekt av storleken size, returnerar pekare till utrymmet eller NULL om det inte fanns. Nollställer dessutom utrymmet. Utgör ett alternativ till malloc(). Bild 58 Dynamisk minnesallokering (forts.) void *realloc(void *ptr, size_t newsiz); Utökar eller minskar utrymmet som pekas ut av ptr till den nya storleken newsiz. Returnerar pekare till början av det förändrade utrymmet. Obs! utrymmet måste finnas på heapen, dvs. ha allokerats tidigare genom malloc(), calloc() eller realloc(). Tas upp på en senare föreläsning. void free(void *ptr); Avallokerar utrymme som pekas ut av ptr och som skall ha allokerats tidigare genom anrop av malloc(), calloc() eller realloc(). Får absolut inte göras på utrymmen som inte finns på heapen eller som redan har avallokerats. Endast hela det utrymme som allokerats kan avallokeras - dvs. man kan inte avallokera delar av ett sådant utrymme. Motsvarar Pascals Dispose, har ingen motsvarighet i Java. Bild 59 6

Mer om dynamisk minnesallokering Minne som allokeras med malloc(), calloc() eller realloc() är placerat på heapen. Utrymmena är namnlösa och åtkomliga endast genom pekare från statiska eller lokala pekarvariabler (precis som objekt i Java). Utrymmena förblir allokerade tills programmet friställer dem med free() (eller med realloc()). T.ex. påverkas de inte av att en funktion som allokerat dem terminerar det som städas bort automatiskt efter ett funktionsanrop är funktionens lokala data på stacken, inte utrymmen på heapen. Det är programmerarens ansvar att friställa dynamiskt allokerade utrymmen som inte längre används. Program som inte friställer sådana utrymmen är felaktiga om nya utrymmen ständigt allokeras, t.ex. i en loop, utan att friställas, förbrukar programmet heaputrymme och kommer så småningom att krascha. Detta kallas minnesläckage (memory leak). Dessvärre kan det vara svårt att upptäcka sådana fel: vid korta testkörningar beter sig programmet som väntat. När ett program har terminerat friställs hela programmets utrymme. Program som just ska terminera behöver alltså inte friställa dynamiskt allokerat minne. Bild 60 Exempel anpassning av stränglängder Om man ska läsa in och lagra många strängar är det onödigt att lagra dem alla i maximerade utrymmen, bättre att ha ett maximerat utrymme för inläsning och efter inläsning dynamiskt allokera så mycket utrymme som behövs för just den strängen: struct person{ int id; char *namn; int vikt, skonr; ; struct person lasperson(void){ struct person p; char buff[1024]; printf( Ange id och namn: ); scanf( %d %1024s, &p.nr, buff); while(getchar()!= \n ) ; p.namn = malloc(strlen(buff)+1); /* Borde kolla om minnet fanns */ strcpy(p.namn, buff); p.vikt = 0; p.skonr = 0; return p; Bild 61 7

Exempel en länkad lista #include <stdlib.h> #include <string.h> struct object { char *data; struct object *next; ; struct object *makeobj(char *d){ struct object *obj; obj=malloc(sizeof(struct object)); if (obj==null) { fprintf(stderr, Minnet slut! ); exit(exit_failure); obj->data=malloc(strlen(d)+1); if (obj->data==null) { fprintf(stderr, Minnet slut! ); exit(exit_failure); strcpy(obj->data, d); obj->next=null; return obj; Bild 62 Fortsättning på exemplet void addfirst(struct object **first,struct object *ny){ ny->next=*first; *first=ny; void removefirst(struct object **first){ if (*first!= NULL){ struct object *away = *first; *first = (*first)->next; free(away->data); free(away); void printall(struct object *first){ struct object *tmp; for(tmp=first; tmp!=null; tmp=tmp->next) printf( %s\n, tmp->data); int main(void){ const char *namn[]={ jozef, stefan, gustaf, johan ; struct object *first=null; int i; for(i=0; i<4; i++) addfirst(&first, makeobj(namn[i])); printall(first); Bild 63 8

Typnamndefinitioner Egna namn för datatyper kan definieras med användning av lagringsklassen typedef. Sådana deklarationer inleds med ordet typedef, ser i övrigt ut som om man deklarerade en variabel av aktuell typ men definierar ett nytt namn för typen istället för en variabel: typedef char *Charptr; Charptr kan nu användas istället för char *. Exempel på användning: typedef struct object *Objptr; typedef struct object { int data; Objptr next; Object; Objptr makeobj(int d){ Objptr obj; obj=malloc(sizeof(object)); Bild 64 Separatkompilerade moduler En separatkompilerad modul ser ut som ett C-program utan funktionen main(). En sådan modul kan användas för att samla och separatkompilera en mängd funktioner och variabler som tillsammans tillhandahåller viss väl avgränsad funktionalitet (t.ex. hantering av en länkad lista osv.). Andra moduler får tillgång till modulens funktioner genom att i källkoden deklarera funktionernas prototyper. Tillgång till variabler erhålles genom att man deklarerar dessa variabler med extern-deklarationer. Eventuella typdefinitioner måste upprepas. Istället för att göra på detta sätt brukar man samla dessa funktionsprototyper, extern-deklarationer och typdefinitioner i en separat textfil, kallad headerfil. Filtypen för en headerfil brukar vara.h. En sådan headerfil inkluderas sedan av alla moduler som skall använda denna moduls funktioner, variabler och typer. Den bör inkluderas även av denna modul själv, för att eventuella motsägelser skall kunna upptäckas vid kompilering. Bild 65 9

Separatkompilering, #include-direktiv Kompilering av en separat modul görs i gcc med flaggan -c som anger att endast kompilering skall göras (undertrycker länkning): gcc -c -g -Wall modul1.c Detta skapar objektkoden på filen modul1.o Vid länkning måste alla moduler anges: gcc -g prog.o modul1.o modul2.o -o prog Kompilatorn får information om vad de externt definierade namnen står för genom att läsa headerfiler. Headerfiler inkluderas i källkoden med #include-direktivet: #include <stdio.h> #include modul1.h Filnamn som omges med < och > sökes på en standardkatalog. Filnamn som omges med sökes först på aktuell katalog. Filnamnet kan innehålla en sökväg, men helst styr man sökning genom flaggor till kompilator. T.ex. i GCC kan man använda flaggan -Isökväg till gcc-kommandot: gcc c g Wall IC:\minlib\include modul.c Bild 66 Globala variabel över flera moduler Ibland vill man att flera moduler ska kunna hantera samma variabler. En sådan variabel får endast vara definierad på ett enda ställe. Definitionen får alltså inte ligga i en headerfil, eftersom headerfilen antagligen inkluderas i flera moduler. Headerfiler innehåller alltså normalt inga definitioner, endast deklarationer med information till kompilatorn (typdefinitioner, funktionsprototyper o.s.v.). För att möjliggöra användning av samma variabel definieras variabeln i en enda moduls källkod, och i modulens headerfil extern-deklareras variabeln: modula.h /* Headerfil för modula */ extern int antal;... modula.c /* Källkodsfil för modula */ int antal = 13;... Bild 67 10

Unioner En union är en post vars medlemmar lagras i samma utrymme (istället för att lagras efter varandra som i vanliga poster). Detta gör att en viss union-variabel vid en viss tidpunkt bör betraktas som innehållande en enda medlem. En annan variabel av samma typ eller samma variabel vid en annan tidpunkt kan dock betraktas som innehållande en annan medlem. Unioner används främst i situationer då variabler med värden av olika typer skall hanteras i samma datastruktur samt i situationer då samma minnesutrymme skall ges olika alternativa tolkningar. Deklaration och medlemsåtkomst liknar poster: union value{ float fval; int ival; char cval; char sval[10]; ; union value v1, v2; v1.fval=3.5; strcpy(v2.sval, Jozef ); Bild 68 Unioner (forts.) Oftast används unioner som medlemmar i poster där man även lagrar en kod som anger vilken unionsmedlem som är aktuell: struct variabel{ char type; union value val; ; struct variabel data[10]; void printval(struct variabel var){ switch(var.type){ case d : printf( %d, var.val.ival); break; case f : printf( %f, var.val.fval); break;... Bild 69 11

Uppräkningskonstanter Uppräkningskonstanter är ett bekvämt sätt att deklarera namn på heltalskonstanter (som helst skall ha något samband med varandra): enum vdag {MAN, TIS, ONS, TORS, FRE, LOR, SON; Konstanterna tilldelas av kompilatorn värden från 0 och uppåt, men man kan ange vilka värden de skall ha, kompilatorn fortsätter sedan uppräkningen. Flera konstanter kan ha samma värde: enum vissaascii {BELL=7, NEWLINE=10, LINEFEED=10, VTAB, FORMFEED, RETURN, ENTER=13, ESC=27, DEL=127; Man kan deklarera variabler av en enum-typ: enum vdag v1, v2; men det blir vanliga int-variabler. Bild 70 12