Föreläsning 5: Introduktion av pekare

Relevanta dokument
Föreläsning 6: Introduktion av listor

Tentamen Grundläggande programmering

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

*Pekarvärden *Pekarvariabler & *

Exempel på ett litet Ada-program

Omgivningar. Omgivningar är viktiga eftersom de avgör vilka namn som är synliga och därmed dessas innebörd och de värden som är förknippade med dem.

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Att använda pekare i. C-kod

Föreläsning 4: Poster

TDDC76 - Programmering och Datastrukturer

5 Grundläggande in- och utmatning

TDIU01 - Programmering i C++, grundkurs

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Föreläsning 5-6 Innehåll

Föreläsning 3-4 Innehåll

[] Arrayer = Indexerad variabel

Inledande programmering med C# (1DV402) 27+15=42 1 (22)

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

Övningsuppgifter kapitel 8

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Föreläsning 7: Filer

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

Programmeringsteknik med C och Matlab

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

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

TDIU01 - Programmering i C++, grundkurs

Övningsuppgifter till föreläsning 2 Variabler och uttryck

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

TDDC76 - Programmering och Datastrukturer

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

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

Föreläsning 8 Programmeringsteknik och Matlab 2D1312/2D1305. Klass Object, instans av klass public/private Klassvariabler och klassmetoder

Föreläsning 0: Introduktion av Ada

Föreläsning 10. Pekare (Pointers)

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

Enkla datatyper minne

Imperativ programmering. Föreläsning 2

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

Föreläsning 2. Variabler, tilldelning och kodblock{} if-satsen Logiska operatorer Andra operatorer Att programmera

Typsystem. Typsystem... Typsystem... Typsystem... 2 *

Typsystem. DA2001 (Föreläsning 23) Datalogi 1 Hösten / 19

Motivation. Programmeringsuppgift: En första ansats: Lagra info om anställda Håll reda på varje anställds närmaste chef. som också är en anställd!

Grundläggande programmering med C# 7,5 högskolepoäng

2 Pekare och dynamiska variabler.

TDDC77 Objektorienterad Programmering

SMD 134 Objektorienterad programmering

Alla filer som bearbetar PHP script ska avslutas med ändelsen.php, exempelvis ska en indexsida till en hemsida heta index.php

Objektorienterad programmering

Tommy Färnqvist, IDA, Linköpings universitet

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Föreläsning 6 pekare och pekare tillsammans med arrayer

TDIU01 - Programmering i C++, grundkurs

Användarhandledning Version 1.2

TENTAMEN. Kurs: Objektorienterad programmeringsmetodik 5DV133 Ansvarig lärare: Anders Broberg. VT-13 Datum: Tid: kl

Objektorienterad programmering

KOMPLETTERANDE HEMTENTAMEN TDDB53

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

Java, klasser, objekt (Skansholm: Kapitel 2)

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

Uppgiften är att beskriva en kvadrat i ett Java program. En första version av programmet skulle kunna se ut så här:

1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

Föreläsning 3.1: Datastrukturer, en översikt

Variabler och konstanter

Objektorienterad Programmering (TDDC77)

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Om att lära sig programmera. Föreläsning 1-2 Innehåll.

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Kort om klasser och objekt En introduktion till GUI-programmering i Java

Det finns många flaggor till g++,

Poster. Vi har ofta behov av att behandla klumpar av data som i sig är inhomogena men sett över ett helt register har klumparna lika struktur.

Laboration 1 Introduktion till Visual Basic 6.0

2D1311 Programmeringsteknik för Bio1 och Bio2, vt 2003 Fiktivt prov På flervalsfrågorna är endast ett svar rätt om inget annat anges i frågan! Det rik

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

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

TENTAMEN TDDB53. Programmering i Ada för MI (provkod TEN2) den 7 april 2010 kl Institutionen för datavetenskap, IDA Olle Willén mars 2010

Pascal. Vi har ofta behov av att behandla klumpar av data som i sig är inhomogena men sett över ett helt register har klumparna lika struktur.

4 Sammansatta datatyper

Poster... Poster. Poster... Poster...

Uppgift 1 ( Betyg 3 uppgift )

kl Tentaupplägg

Datastrukturer. Erik Forslin. Rum 1445, plan 4 på Nada

Prova på-laboration i Ada

Typkonvertering. Java versus C

KOMPLETTERANDE HEMTENTAMEN TDDB53

Föreläsning 3: Typomvandling, villkor och val, samt textsträngar

Tentamen OOP

Klassdeklaration. Metoddeklaration. Parameteröverföring

Deklarationer/definitioner/specifikationer

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

Standardfilerna Input och Output

Standardfilerna Input och Output. Filer... Filer... vanlig utbyggnad för ökad dynamik. Filer... filtyper

Värmedistribution i plåt

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

Anteckningar 1: Grundläggande saker

Föreläsningsanteckningar, Introduktion till datavetenskap HT S4 Datastrukturer. Tobias Wrigstad

Linköpings Tekniska Högskola Institutionen för Datavetanskap (IDA), Software and Systems (SaS) (c) Klas Arvidsson

Klasser och objekt. Henrik Johansson. August 20, 2008

Transkript:

Föreläsning 5: Introduktion av pekare Det bör påpekas att det som tas upp i introduktionen inte är reella exempel på kod. Man anväder inte pekare till att peka på enstaka heltal som i exemplen nedan, men introduktionen är bara till för att få grepp om skillnaderna mellan pekare och det som refereras. En pekare är en variabel som innehåller en "referens" till ett data. Datat kan vara av godtycklig datatyp (t.ex. ett heltal eller en post eller en array). Man kan säga att pekaren innehåller en adress till ett minnesutrymme (i primärminnet) som innehåller datat man pekar på. För att rita upp hur detta kan se ut antar vi att vi har en pekare som pekar på (refererar) ett heltal. Variabeln P1 får vara pekaren. P1 4711 För att deklarera P1 krävs att man har en datatypsbeskrivning som anger vad man skall peka på (i detta fall ett heltal). Denna görs på följande sätt: P1 : Integer_Access; Identifieraren "Integer_Access" är det namn som vi hittat på själva. På rad 2 står det reserverade ordet "access" som används för att ange att det är en pekartyp och "Integer" som anger att denna typ skall peka på just heltalsdata. Efter deklarationen kan P1 innehålla ett godtyckligt värde, d.v.s. pekaren pekar på ett godtyckligt minnesutrymme. Om man använder sig av en pekare som pekar på något minnesutrymme som man inte vet vad det är kan man råka ut för två olika problem: 1. Minnesutrymmet "ägs" inte av programmet och får därför inte användas alls. Om minnesutrymmet refereras av programmet resulterar detta i att programmet "kraschar" ("exception" fås). Ett fel av denna art går lätt att hitta programmeraren kan se var programmet kraschar. 2. Minnesutrymmet råkar vara en del av programmet (detta är allvarligare än det förra). Nu är det alltså "tillåtet" att referera minnesutrymmet och detta kan leda till att man förstör data som inte alls har med pekaren att göra eller kanske ändrar i kod/instruktioner som skall utföra något. Detta fel kan resultera i att programmeraren får svårt att hitta var felet ligger. Symptomen kan dyka upp långt efter orsaken.

För att slippa dessa problem gör man så att man tilldelar pekaren ett värde som anger att den inte pekar på/refererar något alls. För att göra detta finns det en pekarkonstant som heter "null" (blanda inte ihop denna med satsen "null;" som utför "ingenting"). P1 := null; Bild för att visa hur P1 "ser ut": P1 Man kan tilldela pekaren värdet "null" redan i deklarationen analogt med andra datatyper. P1 : Integer_Access := null; När man vill att en pekare skall peka på ett minnesutrymme kan man göra på två sätt. Dels kan man skapa ett minnesutrymme (ta ett ledigt utrymme i datorn och binda det till programmet) och dels kan man låta en pekare referera samma minnesutrymme som en annan pekare. Om man försöker skapa ett minnesutrymme och det inte finns minnesutrymmen lediga i datorn reses ett undantag (programmet kan alltså krascha). Exempel på program som visar de två fallen ovan: P1, P2 : Integer_Access; Ta ett minnesutrymme som är lagom stort för ett heltal och bind det till programmet. Låt därefter pekaren peka på detta minnesutrymme. OBS! Minnesutrymmet har ett odefinerat värde! Låt en annan pekare peka på SAMMA minnesutrymme som P1. P2 := P1; "Minnesadressen" i P1 kopieras till P2. En liten bild för att visa hur två pekare kan peka på samma minnesutrymme: P1???? P2

Ett litet program som visar ett antal legala/illegala operationer på pekare samt jämförelser med heltal. with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; P1, P2 : Integer_Access; I1, I2 : Integer; I1 := 7; I2 := I1; P1 := null; P2 := P1; if P2 = null then Put("Berta"); Berta skrivs ut eftersom P2 har värdet null. P1 := I1; FEL!!! P1 ej samma typ som I1. Put(I1); Put(P1); FEL!!! Finns ej Put för pekare! Put(P1.all); Ok. P1.all är av typen Integer. Vad skrivs ut? Odefinerat värde. P1.all := I1; Put(P1.all); Tillåtet! I1 är en Integer och P1 pekar på en Integer. Nu skrivs värdet 7 ut på skärmen. P2 := P1; P2 pekar nu på samma utrymme som P1 pekar på. P2.all := 4; OBS! P2.all tilldelas värdet. Put(P1.all); P1.all har nytt värde! Talet 4 skrivs ut! if P1.all = P2.all) then Put("Kalle"); Kalle skrivs ut eftersom P1 och P2 båda pekar på en 4:a. Put("Nisse"); Nisse skrivs ut eftersom P1 och P2 pekar på SAMMA minnesutrymme. P1.all := P2.all;

if P1.all = P2.all) then Put("Kalle"); Kalle skrivs ut eftersom P1 och P2 båda pekar på en 4:a. Put("Nisse"); Nisse skrivs INTE ut eftersom P1 och P2 inte pekar på SAMMA minnesutrymme. end Main; Antag att programmet avslutas på detta sätt. Det vi vet sen tidigare är att alla variabler i ett program "försvinner" (minnesutrymmet för respektive variabel lämnas tillbaka till datorns operativsystem), men vad händer med de minnesutrymmen som vi har bundit till programmet som pekarna håller reda på? Generellt sett kan man bara säga att det beror på hur kompilatorn har gjort. Ibland kan det vara så att kompilatorn inte har brytt sig om att lägga ut kod så att dessa dynamiskt bundna minnesutrymmen lämnas tillbaka. Ibland har kompilatorn gjort detta. Om det är så att dynamiskt minnesutrymme inte "lämnas tillbaka" till operativsystemet kommer detta att leda till att man får mindre och mindre med plats att köra andra program. Till slut måste datorn stängas av och startas om för att man skall kunna köra några program alls. Om man inte lämnar tillbaka dessa minnesutrymmen får man något som kallas för en minnesläcka (programmet "läcker" minne). Minnesläckor kan också uppstå under tiden man kör sitt program. T.ex. om programmeraren gjort fel i sitt program. Ett litet exempel på hur detta skulle kunna gå till. Variabeln P1 kan bara hålla reda på en minnesadress och då vi för andra gången tar ett minnesutrymme och låter P1 peka på detta blir det första minnesutrymmet att "hänga i luften". Programmet äger det första minnesutrymmet som skapades, men kan inte komma åt det. Det är omöjligt att få tillbaka ett minnesutrymme som tappats på detta sätt under tiden programmet körs. När programmet avslutas är det helt beroende på kompilatorn om minnet återlämnas eller ej. Kommentar: I vissa språk har man gjort så att minnesutrymmen automatiskt återlämnas till operativsystemet om de inte längre refereras, men detta tar tid från programmet. En "slarvig" programmerare kan därför få ett program att fungera tack vare detta, men det kanske inte hade behövts om programmeraren haft en annan algoritm. För att vara säker på att programmet alltid lämnar tillbaka sina dynamiska minnesutrymmen skall man som programmerare alltid se till att detta görs innan programmet avslutas. För att lösa detta använder man den generiska proceduren som heter "Ada.Unchecked_Deallocation". Denna är endast till för att återlämna minnesutrymmen som pekare refererar. Ett exempel på användning.

with Ada.Unchecked_Deallocation; procedure Free is new Ada.Unchecked_Deallocation(Integer, Integer_Access); P1 : Integer_Access; P1.all := 7; Free(P1); end Main; Vi skapar en instans av Ada.Unchecked_Deallocation och döper denna ("Free" i vårt exempel). För att göra detta måste vi skicka med två argument. Det första anger vad det är för typ på minnesutrymmet vi refererar (Integer i exemplet) och det andra är pekartypen som refererar denna typ av minnesutrymmen (Integer_Access i exemplet). När vi sen anropar proceduren Free skickar vi med den pekare som pekar på det minnesutrymme vi vill lämna tillbaka (i vårt exempel P1). I proceduren Free kommer då följande att ske: 1. Minnesutrymmet som P1 pekar på lämnas tillbaka. 2. Pekaren P1 tilldelas värdet "null", d.v.s. den pekar inte på något minnesutrymme längre. Steg 2 är något som är lite specifikt för Ada. Det finns inte i alla språk och därför kan man om man vill vara lite övertydlig tilldela P1 värdet "null" efter anropet till Free, men det är alltså inte nödvändigt i Ada. TIPS: För att få en bättre förståelse kan man ta fram fem personer ur den grupp man undervisar och låta två av dem agera pekare och de tre övriga får vara dynamiska minnesutrymmen. För att man skall få så bra effekt som möjligt är det bra om "pekarna" (två korta personer) får pekarlappar med en färg, med pekarvärden "pekare som pekar konstigt", "pekare som pekar rakt" respektive "null", och "minnena" (tre långa personer) får minneslappar med en annan färg. De heltalsvärden som behövs till progammet nedan är 4, 7 respektive? (=odefinerat värde). Följande program kan användas för att exemplifiera. Antag att det finns givet lämpliga deklarationer! Kommentarerna skall inte synas utan är bara till för den som undervisar.

P1 := null; P2 := new Integer; P2.all := 7; Put(P2); FEL!!! Stryk denna sats. P1 := P2; P1 := 4; FEL!!! Stryk denna sats. P1.all := 4; Put ("Kalle"); if (P1.all = P2.all) then Put("Nisse"); P2 := new Integer; P2.all := 4; Put ("Kalle"); Skrivs ej ut! if (P1.all = P2.all) then Put("Nisse"); Minnesläcka!!! P1.all := P2.all; Put ("Kalle"); Skrivs ej ut! Free(P1); Eventuell minnesläcka beroende på kompilatorn!!! Generellt gör man inte program som har pekare till heltal. För det mesta används pekare när man vill peka på poster. Antag att vi skall skapa två pekare som kan referera poster som innehåller persondata. Exempel: type Person_Type is record Name : String(1..20); Age : Integer; end record; type Person_Access is access Person; P3, P4 : Person_Access; Samma operationer som tidigare är tillåtna så vi skulle kunna skriva följande program för att skapa en personpost, bearbeta denna lite och sen lämna tillbaka minnesutrymmet (detta kallas att man "avallokerar" minnesutrymmet av många).

with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with Ada.Unchecked_Deallocation; type Person_Type is record Name : String(1..20); Age : Integer; end record; type Person_Access is access Person; procedure Free is new Ada.Unchecked_Deallocation(Person_Type, Person_Access); procedure Put(Item : in Person_Type) is Skriv ut postens innehåll på skärmen. Put(Item.Name); Put(Item.Age); end Put; P3 : Person_Access; Skapa en post och stoppa in data i den. P3 := new Person_Type; P3.all := ("Bo Nilsson Andersson", 25); Eller... P3.all := (Name => "Bo Nilsson Andersson", Age => 25); Annat sätt att stoppa in data i posten. P3.all.Name := "Bo Nilsson Andersson". Eller om man vill kan man ta bort ".all". P3.Name := "Bo Nilsson Andersson". Anropa din egen Put. Put(P3.all); Men här är det INTE ok att ta bort ".all". Put(P3); FEL!!! Finns ingen Put för pekare. Lämna tillbaka minnesutrymmet. Free(P3); end Main; Något som är ännu vanligare är att man använder pekare till att skapa listor av poster. Detta tas upp i "Introduktion av listor".