Pointers, arrays & dynamische geheugen

Slides:



Advertisements
Verwante presentaties

Advertisements

Instructie Programmeren Task 1 5JJ70. Task 1.1: Hello World •Klik naast de laatste accolade in de grijze kantlijn om een breakpoint neer te zetten, anders.
Algoritmen en Datastructuren (ALDAT)
PHP & MYSQL LES 03 PHP & DATABASES. PHP & MYSQL 01 PHP BASICS 02 PHP & FORMULIEREN 03 PHP & DATABASES 04 CMS: BEST PRACTICE.
Instructie Programmeren Task 8 5JJ70. PAGE 2 Task 8: Double Linked List Het doel van deze opdracht is: Het opbouwen van een tweetal klassen, die samen.
Practica Computerlinguistiek Tekst en uitleg:
Instructie Programmeren Task 1 5JJ70. Task 1.1: Hello World Klik naast de laatste accolade in de grijze kantlijn om een breakpoint neer te zetten, anders.
Instructie Programmeren Debuggen 5JJ70. Debuggen: Wat is het probleem Je programma compileert, maar werkt niet zoals verwacht, wat nu? Vraag je af: wat.
1 Tentamen 21 januari 2008 uitleg Algemene kennisvragen a)“Wat verstaan we onder de complexiteit van een algoritme?” –Cruciaal: wat gebeurt er met.
Hoofdstuk 6: Controle structuren
VHDL Peter Slaets KHLim Functies en procedures Functies –type conversie functies »bit vector to integer en omgekeerd –verkorte componenten met maar 1 output.
1 Datastructuren Lijstjes (Stacks & Queues) Onderwerp 7.
Hoofdstuk 2 Hallo, C# !.
Les 2 Basisbouwstenen (deel 1)
Instructie Programmeren Task 5
Inleidend probleem Data structuur (hiërarchie van classes)
Numerieke Natuurkunde
Algoritmen en Datastructuren (ALDAT) EVMINX4 Dagdeel 2.
MICPRG Les 11 Microcontroller Programmeren in C. 112 Datastructuren in C Werkgeheugen (PC en microcontroller): Statische datastructuren (vaste grootte):
GESPRG Les 7 Gestructureerd programmeren in C. 92 Verwisselen Schrijf een functie waarmee twee int variabelen verwisseld kunnen worden. void wissel(int.
JAVA -- H51 CONSTRUCTOR –- COPY-CONSTRUCTOR 1Constructor: Dezelfde naam als de klasse Wordt uitgevoerd d.m.v. new Initialisatie van de (private) attributen.
PHP functies.
Consoletoepassing Variabelen Klassen
1 Datastructuren Introductie tot de programmeeropgaven in C++ Jan van Rijn
Hogeschool HZ Zeeland 19 augustus 2003augustus 2003 Data Structuren & Algoritmen Week 3.
Deel I: Programmeertaal C 6. Arrays en Pointers
P. 1 Vakgroep Informatietechnologie Structuur Deel II C++ Classes Namespaces Type casting Reference types Constructors en Destructors Memory Management.
Tircms02-p les 4 Preprocessor In- en uitvoer Diversen.
Arrays Hoofdstuk 14 Hoofdstuk 14.
Tircms03-p les 6 Templates. Functietemplates void verwissel(int &x, int &y); { int w=x;x=y;y=w;} Dezelfde functie voor meerdere types heet een functietemplate.
Tircms03-p les 2 Hfdst 3,4 Meer operatoren Functies.
Tircms02-p les 3 Functies Strings Structuren. Functies 1. main() 2. { int k; k = 10 ; printf(“%d\n”,fac(k)); } 3. int fac(n) int n; 4. { int f; f= 1;
Tircms02-p les 2 Meer operatoren Arrays en pointers Types en conversie.
tircms02-p les 1 Operating Systems practicum
Tircms03-p les 4 Klassen. Abstracte datatypes in C struct stack { char info[100]; int top; }; void reset(stack *s) { s->top = -1; } void push(stack *s,
Tircms03-p les 1 C++ voor C-kenners Voor Technische Informatica.
Java C++ nVeilig nMachine- onafhankelijk nVeel libraries, ook voor Internet-I/O Snel Native executables Libraries optimaal voor specifiek OS.
Instructie Programmeren Task 7
De laatste essentiele dingen.  Classes ◦ Syntax ◦ Constructors & Destructors  Header & Source Files ◦ Waar gebruiken we dit voor  Compiler Theorie.
Graphics, input & more!.  Graphics  Input  Sound  … game loop?
Studiehouding Ergens verstand van krijgen kost tijd… Uren die je alleen in je boeken doorbrengt maken het verschil. Er is niets mis met onafhankelijkheid.
 C++ heeft een inheritance mechanisme  Manier om functionaliteit te ‘erfen’ van een parrent class ◦ Polymorphisme ◦ Zoals we het ook in C# kennen.
Les 3 - Operators Workshop Php Basic. ICT Academy Php Basic Content Operators Wiskundig Toewijzing Vergelijking.
Loops en errors Array's Random try catch for loop while loop do while loop.
Wat is SQL (1)? SQL (Structured Query Language):  is een zeer krachtige taal met een beperkt vocabulaire (aantal ‘woorden’)  is declaratief (‘WAT’ niet.
GEGEVENSSTRUCTUREN IN.NET. Inleiding  Enumerated type  Structure  Collecties  Typed collections  Untyped collections.
18 Februari 2013 Where friends have access to your privates!
Gameprogrammeren: Objecten en geheugen
Gameprogrammeren: Lists en interfaces
Hoofdstuk 9.2 Strings.
De programmeertaal C++
Gameprogrammeren: Expressies
Windows-applicatie using System.Windows.Forms; using System.Drawing;
Gameprogrammeren: Methoden
Tinpro015b-les 1 C++ voor C-kenners Voor Technische Informatica.
Basis Gameprogrammeren
Tinpro015b-les5 Invoer en Uitvoer.
Tinpro015b-les3 Hfdst 3,4 Meer operatoren Functies.
C++ • C++ als een verbetering van C • Abstracte datatypen met classes • Constructoren en destructoren • Subklassen • binding van functies 1.
Tinpro015b-les6 Templates.
Arjan Egges & Paul Bergervoet
Tinpro015b-les4 Klassen.
Wat gaan we doen? Herhaling ARM assembler instructies
SQL Les February 2019.
Software Development fundamentals
Software Development fundamentals
Software Development fundamentals
Gameprogrammeren: Arrays
Python – For loop + strings
Transcript van de presentatie:

Pointers, arrays & dynamische geheugen The scary stuff Gydo deze keer niet aanwezig Practicum feedback graag

Wat is een pointer? Verwijzing naar een stuk geheugen Enge spul in C++ Bron van al het kwaad … Veel van jullie hebben wel eens iets gehoord over pointers

Wat is een pointer?

Wat is een pointer? Beetje net een referentie in C# Maar niet helemaal! Verwijst naar een stuk geheugen net als in C#

Pointer voorbeeld! Output: 0026F7E4 #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer; // Point to myNumber myPointer = &myNumber; cout<<myPointer; return 0; } Output: 0026F7E4 Wat komt hier uit? Paar nieuwe dingen: Int aanmaken Pointer aanpaken Pointer laten wijzen naar de integer Printen de pointer Nieuwe syntax: * Teken om pointer aan te geven & teken, geheugenadres Hoe outputten we de waarde?

Pointer voorbeeld! Output: 10 #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer; // Point to myNumber myPointer = &myNumber; cout<<*myPointer; return 0; } Output: 10 Door * toe te voegen aan de variabele naam, geven we aan dat we de waarde aan willen spreken.

Pointer syntax Type gevolgd met een *-teken int* ook een type! Later meer hierover Zonder * verwijzen we naar de pointer Met * naar de waarde

Pointer syntax voorbeeld #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int mySecondNumber = 20; int* myPointer = &myNumber; *myPointer = 100; myPointer = &mySecondNumber; *myPointer = 200; cout<<myNumber<<endl; cout<<mySecondNumber<<endl; return 0; } Output: 100 200 Twee integers Één integer pointer We laten eerst de pointer verwijzen naar myNumber Door * voor de pointer te zetten, spreken we de waarde aan Zonder de * voor de pointer veranderen we waar de pointer naar wijst

Pointer syntax - andere types #include <iostream> using namespace std; int main(int argc, char* argv[]) { float myFloat = 1.5f; float *myPointer = &myFloat; cout<<*myPointer; cin.ignore(); return 0; } Werkt ook met floats! Andere notatie: spatie tussen * en type

Pointer syntax - andere types #include <iostream> using namespace std; int main(int argc, char* argv[]) { float myFloat = 1.5f; int *myPointer = &myFloat; cout<<*myPointer; cin.ignore(); return 0; } Een int pointer kan alleen verwijzen naar integers Error 1 error C2440: 'initializing' : cannot convert from 'float *' to 'int *’

Pointer syntax - andere types #include <iostream> using namespace std; int main(int argc, char* argv[]) { float myFloat = 1.5f; int *myPointer = (int*)&myFloat; cout<<*myPointer; cin.ignore(); return 0; } Output: 1069547520 Met een cast kunnen we het wel naar een int pointer forceren. Float geheugenlocatie interpreteren als een int! Wat heb je er nu aan? Vrij weinig.

Pointer syntax – more! #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; int* myOtherPointer = myPointer; *myOtherPointer = 100; cout<<myNumber; cin.ignore(); return 0; } Output: 100 Pointers kun je ook gewoon aan elkaar toewijzen.

Pointer syntax – pointer to pointer #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; int** myOtherPointer = &myPointer; **myOtherPointer = 100; cout<<myNumber; cin.ignore(); return 0; } Output: 100 Pointers kunnen ook naar andere pointers verwijzen Int** pointer naar pointer, je kan er ook meer sterretjes in zetten.

Pointer syntax – pointer to pointer #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; int** myOtherPointer; *myOtherPointer = myPointer; **myOtherPointer = 100; cout<<myNumber; cin.ignore(); return 0; } Output: 100 Zonder * voor de myOtherPointer kun je alleen een int** toewijzen (zie vorige slide) Met één * voor myOtherPointer kun je een int* aan toewijzen Met twee *-tekens kun je een int toewijzen

Pointer syntax #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; *myPointer++; cout<<myNumber<<endl; cout<<*myPointer<<endl; cin.ignore(); return 0; } Output 10 1586225894 Het lijkt of we de waarde waar onze pointer naar verwijst verhogen. Niet het geval! ++ heeft voorrang op * We voeren ++ uit op de pointer locatie => locatie van pointer verandert!

Pointer syntax #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; (*myPointer)++; cout<<myNumber<<endl; cout<<*myPointer<<endl; cin.ignore(); return 0; } Output 11 We fixen dit door haakjes toe te voegen. Toch interessant dat we ++ op een pointer kunnen doen

Pointer syntax – pointer ophogen? #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; cout<<myPointer<<endl; myPointer++; cout<<(int)myPointer - (int)&myNumber<<endl; return 0; } Output 0036FAC0 0036FAC4 4 sizeof(int) We outputten eerst het adres waar myPointer naar verwijst Daarna hogen we de pointer op. Dan outputten we opnieuw het adres waar myPointer naar verwijst Daarna outputten we het verschil tussen de nieuwe adres en het oude.

Pointer syntax – pointer ophogen? #include <iostream> using namespace std; int main(int argc, char* argv[]) { short myNumber = 10; short* myPointer = &myNumber; cout<<myPointer<<endl; myPointer++; cout<<(int)myPointer - (int)&myNumber<<endl; return 0; } Output 0038FAF4 0038FAF6 2 sizeof(short) Zelfde, maar dan met shorts

Pointer syntax – pointer ophogen? #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 10; int* myPointer = &myNumber; cout<<myPointer<<endl; myPointer = myPointer + 3; cout<<(int)myPointer - (int)&myNumber<<endl; return 0; } Output 002AF83C 002AF848 12 Weer terug naar ints Getal optellen bij pointer.

Arrays! Blok aaneengesloten geheugen Verwijzing naar begin

Voorbeeld – pointer naar array #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myArray[10]; for(int i = 0; i < 10; i++) myArray[i] = i*5; int* myPointer = &myArray[0]; cout<<*(myPointer+4)<<endl; cin.ignore(); return 0; } #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myArray[10]; for(int i = 0; i < 10; i++) myArray[i] = i*5; int* myPointer = &myArray[0]; myPointer += 4; cout<<*myPointer<<endl; cin.ignore(); return 0; } Output: 20 We creëren een array van lengte 10 Initialiseren de array {0, 5, 10, 15 etc..} Laten myPointer verwijzen naar de eerste element van onze array Tellen 4 op bij de pointer, waardoor het 4*4bytes verplaatst Kijken naar de waarde Zelfde functionaliteit als de index operator []!

Voorbeeld – Array == pointer? #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myArray[10]; for(int i = 0; i < 10; i++) myArray[i] = i*5; int* myPointer = myArray; myPointer += 4; cout<<*myPointer<<endl; cin.ignore(); return 0; } Output: 20 Bijna zelfde code Array wordt direct toegewezen aan myPointer! Array in essentie niets anders dan een pointer naar eerste element!

Array syntax Initialisatie 2D array declaratie: 2D array initialisatie int myArray[10]; Initialisatie int myArray[] = {0, 1, 2, 3, 4}; 2D array declaratie: int myArray[5][10]; 2D array initialisatie int myArray[3][2] = { {10, 20}, {30, 40}, {50, 60} }; Allemaal syntactische suiker voor het werken met pointers Uitkijken met 2D arrays, is compiler specifiek qua memory management. Inconsistent qua syntax (als je het als parameter mee wil geven) Kan voor vele fouten zorgen Gebruik liever 1D array met size hoogte*breedte

Dynamische geheugen new delete new[] en delete[] Reserveert geheugen en geeft een pointer delete Krijgt een pointer mee, geeft geheugen vrij new[] en delete[] Voor arrays

new en delete Output: 50 #include <iostream> using namespace std; int main(int argc, char* argv[]) { int* myPointer = new int; *myPointer = 50; cout<<*myPointer<<endl; delete myPointer; myPointer = nullptr; cin.ignore(); return 0; } Output: 50 We declareren een int pointer Gebruiken new int om een integer te reserveren Deze kunnen we gebruiken als elk andere pointer. Geheugen vrijgeven met delete Omdat we netjes zijn, zetten we de pointer op null om dubbele deletes te voorkomen.

new[] en delete[] Output: 50 #include <iostream> using namespace std; int main(int argc, char* argv[]) { int* myPointer = new int[5]; myPointer[3] = 50; cout<<myPointer[3]<<endl; delete [] myPointer; myPointer = nullptr; cin.ignore(); return 0; } Output: 50 Alloceren geheugen met new int[5]. Net C# Net zoals dat we de [] operator konden nabootsen met pointer operaties, kan het omgekeerde ook! Elementen accessen met [] operator Geheugen vrijgeven met delete []

Bad allocation Memory allocations kunnen fout gaan Out of memory Standard gedrag: exception. Ja, C++ heeft ook exceptions Liever geen exceptions? Gebruik (nothrow)

Bad allocation Output: 00000000 #include <iostream> #include <new> using namespace std; int main(int argc, char* argv[]) { int* myPointer = new (nothrow) int[500000000]; cout<<myPointer<<endl; delete[] myPointer; cin.ignore(); return 0; } We includen <new> Bij het aanroepen van new[] gebruiken we nothrow, deze is gedefineerd in de <new> header We outputten de geheugenadres. Dit is gelijk aan 0 Check met een if statement of de allocatie is gelukt.

Dynamic allocation #include <iostream> #include <new> using namespace std; int main(int argc, char* argv[]) { int arraySize; cin>>arraySize; int* myPointer = new (nothrow) int[arraySize]; if(myPointer) cout<<"Memory allocated!"<<endl; else cout<<"Out of memory!"<<endl; delete [] myPointer; return 0; } Output: 2000 Memory allocated! De groottes van deze dynamische allocaties kunnen natuurlijk dynamisch (at run-time) worden bepaald. Hier wordt de gebruiker gevraagd om een integer in te voeren. Vervolgens wordt een array van deze grootte gealloceerd. Afhankelijk van of het gelukt is, wordt er iets op de scherm geprint.

Main functie revisisted int main(int argc, char* argv[]) char* argv[] Array van arrays Dus argv is een array van arrays van chars: char**

References Beetje pointer functionaliteit Minder krachtig Veiliger Simpelere syntax

References - voorbeeld #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 50; int& myReference = myNumber; myReference++; cout<<myNumber; cin.ignore(); return 0; } Output: 51 We creëren een reference We laten het verwijzen naar myNumber. Dit kun je niet opslitsen, want een reference is een constante We hogen de reference op myNumber is veranderd

References - voorbeeld #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 50; int* myPointer = &myNumber; (*myPointer)++; cout<<myNumber; cin.ignore(); return 0; } Output: 51 Vergeleken met pointer syntax is het simpeler.

References - voorbeeld #include <iostream> using namespace std; int main(int argc, char* argv[]) { int myNumber = 50; int myOtherNumber = 100; int& myReference = myNumber; myReference++; myReference = myOtherNumber; cout<<myNumber<<endl; cout<<myOtherNumber<<endl; cin.ignore(); return 0; } Output: 101 100 References zijn constant, na creatie kunnen ze niet meer worden aangepast. Bij de tweede assignement wordt de waarde aangepast in plaats van het adres. Minder krachtig, maar simpeler.

Function arguments Output: 2500 #include <iostream> using namespace std; void Kwadraat(int* x) { *x = *x * *x; } int main(int argc, char* argv[]) int myNumber = 50; Kwadraat(&myNumber); cout<<myNumber; cin.ignore(); return 0; Output: 2500 “Pass by reference” van een int We geven adres van myNumber mee, de waarde hiervan wordt vervolgens gewijzigd

Function arguments Output: 2500 #include <iostream> using namespace std; void Kwadraat(int& x) { x = x * x; } int main(int argc, char* argv[]) int myNumber = 50; Kwadraat(myNumber); cout<<myNumber; cin.ignore(); return 0; Output: 2500 Met references wordt het een stuk simpeler.

Collections List<T> Dictionary<Key, Val> Stack<T> vector<T> Dictionary<Key, Val> map<key, val> Stack<T> stack<T> Queue<T> queue<T> En meer… maar deze gebruik je het meest. Veel ingebouwde collecties, waardoor gebruik van dynamische allocaties een stuk minder wordt Minder bugs! Net zoals in C#, heeft C++ wat standaard collecties in de standard template library.

Collections - Vector Output: 3 6 9 #include <iostream> #include <vector> using namespace std; int main(int argc, char* argv[]) { vector<int> myArray; myArray.push_back(3); myArray.push_back(6); myArray.push_back(9); for(int i=0;i<myArray.size();i++) cout<<myArray[i]<<endl; } cin.ignore(); return 0; Output: 3 6 9 Include <vector> Type meegeven, net zoals in List van C# Toevoegen met push_back(). Vergelijkbaar met List.Add() Aantal elementen opvragen met size() Wat ook opvalt, we gebruiken geen new Vector, later meer over met classes.

Collections - Vector Type meegeven push_back() - Toevoegen pop_back() - Verwijderen size() - Aantal elementen clear() - Leegt de collectie [] operator En meer… deze zijn de meest gebruikte

Collections - map Output: 0.6 #include <iostream> #include <map> #include <string> using namespace std; int main(int argc, char* argv[]) { map<string, float> prijzen; prijzen["melk"] = 0.6f; prijzen["chicken"] = 2.5f; prijzen["sate"] = 0.28f; prijzen["jello"] = 1.2f; cout<<prijzen["melk"]<<endl; cin.ignore(); return 0; } Output: 0.6 Key type en value type aangeven Met [] operator inserten en opvragen O(log n) tijd

Collections - map [] operator find() erase() size() begin() end() map<key, value>::iterator Find kun je ook gebruiken om te kijken of een element wel/niet in de collectie zit.

Collections - map int main(int argc, char* argv[]) { map<string, float> prijzen; prijzen["melk"] = 0.6f; prijzen["chicken"] = 2.5f; prijzen["sate"] = 0.28f; prijzen["jello"] = 1.2f; map<string, float>::iterator it = prijzen.find("koffie"); if(it == prijzen.end()) cout<<"Geen koffie"<<endl; else cout<<"Koffie kost "<< it->second <<endl; cin.ignore(); return 0; } We maken een iterator object, dit is een object die naar een element in de verzameling kan verwijzen Ook kun je met een iterator de verzameling doorlopen, later meer hierover. Net enumerators van C# Als een element niet bestaat, verwijst deze naar end()

Collections - map Output chicken => 2.5 jello => 1.2 melk => 0.6 sate => 0.28 int main(int argc, char* argv[]) { map<string, float> prijzen; prijzen["melk"] = 0.6f; prijzen["chicken"] = 2.5f; prijzen["sate"] = 0.28f; prijzen["jello"] = 1.2f; map<string, float>::iterator it; for(it = prijzen.begin(); it != prijzen.end(); it++) cout<< it->first << " => " << it->second << endl; } cin.ignore(); return 0; Met de ++ operator laten we de iterator wijzen naar het volgende element, net als bij pointers.

Collections - stack push() pop() top() Bekijk top element zonder te verwijderen

Collections - queue push() pop() front() back() Voeg toe aan staart Verwijder kop front() back() Access kop of staart zonder verwijderen

Collections – More! Veel meer datstructuren Set Multiset Multimap Priority queue Unordered_map Array En meer!