Felder (Arrays) und Zeiger (Pointers) - Teil I

Ähnliche Dokumente
Felder (Arrays) und Zeiger (Pointers) - Teil I

Felder (Arrays) und Zeiger (Pointers) - Teil I

Felder: Motivation. Felder (Arrays) und Zeiger (Pointers) - Teil I. Felder: erste Anwendung. Felder: erste Anwendung

Dynamische Datentypen

Felder: Motivation. Felder (Arrays) und Zeiger (Pointers) - Teil I. Felder: erste Anwendung. Felder: erste Anwendung. Felder: erste Anwendung

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

Visuelle Kryptographie. Anwendung von Zufallszahlen

Informatik 1 ( ) D-MAVT F2010. Schleifen, Felder. Yves Brise Übungsstunde 5

10. Referenztypen. Referenztypen: Definition und Initialisierung, Call By Value, Call by Reference, Temporäre Objekte

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

9. Referenztypen. Swap! Referenztypen: Definition. Referenztypen

11. Referenztypen. Swap! Referenztypen. Referenztypen: Definition

Datenkapselung: public / private

9. Referenztypen. Referenztypen: Definition und Initialisierung, Call By Value, Call by Reference, Temporäre Objekte, Konstanten, Const-Referenzen

Crashkurs C++ - Teil 1

C++ Teil 6. Sven Groß. 23. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 15

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

11. Referenztypen. Swap! Referenztypen: Definition. Referenztypen

Datenkapselung: public / private

Felder (Arrays) und Zeiger (Pointers) - Teil II. Zeichen, Texte, Caesar-Code, String Matching; Mehrdimensionale Felder; kürzeste Wege

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

1. Zeiger, Algorithmen, Iteratoren und Container. Felder als Funktionsargumente, Zeiger, Iteratoren auf Vektoren, Container

11. Referenztypen. Swap! Referenztypen: Definition. Referenztypen

Datenkapselung: public / private class rational { r.d = 0 int n; int d; // INV: d!= Klassen rational r; r.n = 1; // error: n is private

Programmierung mit C Zeiger

Kontrollfluss. man Verzweigungen und Sprünge. o bisher linear (von oben nach unten) o Für interessante Programme braucht

Universität München, Hans-Peter Kriegel und Thomas Seidl Informatik II a[0] a[1] a[2] a[3] a[n 1]

12. Felder (Arrays) II

Ganze Zahlen. Die Typen int, unsigned int; Auswertung arithmetischer Ausdrücke, arithmetische Operatoren

16. Structs und Klassen I. Rationale Zahlen, Struct-Definition, Operator-Überladung, Datenkapselung, Klassen-Typen

6. Kontrollanweisungen II

18. Dynamische Datenstrukturen I

5. Kontrollanweisungen II

Zeiger: Der Adressoperator &

Informatik. Pointer (Dynamisch) Vorlesung. 17. Dezember 2018 SoSe 2018 FB Ing - SB Umwelttechnik und Dienstleistung - Informatik Thomas Hoch 1

Informatik 1 ( ) D-MAVT F2011. Pointer, Structs. Yves Brise Übungsstunde 6

15. Zeiger, Algorithmen, Iteratoren und Container II

13. Felder (Arrays) II

Datenkapselung: public / private r.d = 0 class rational { int n; int d; // INV: d!= Klassen rational r; r.n = 1; // error: n is private

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

2. Ganze Zahlen. Auswertung arithmetischer Ausdrücke, Assoziativität und Präzedenz, arithmetische Operatoren, Wertebereich der Typen int, unsigned int

1. Ganze Zahlen. 9 * celsius / Celsius to Fahrenheit. (9 * celsius / 5) + 32

Ganze Zahlen. Die Typen int, unsigned int; Auswertung arithmetischer Ausdrücke, arithmetische Operatoren

C++ Teil 7. Sven Groß. 30. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 13

Einführung in die Programmiersprache C

Algorithmen und Datenstrukturen

2. Ganze Zahlen int unsigned int

Grundlagen der Informatik 11. Zeiger

Angewandte Mathematik und Programmierung

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

C++ Teil 5. Sven Groß. 16. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

F Zeiger, Felder und Strukturen in C

Programmier-Befehle - Woche 09

1. Referenzdatentypen: Felder und Strings. Referenz- vs. einfache Datentypen. Rückblick: Einfache Datentypen (1) 4711 r

1. Referenzdatentypen: Felder und Strings

2. Programmierung in C

Zeiger in C und C++ Zeiger in Java und C/C++

C- Kurs 08 Zeiger. Dipl.- Inf. Jörn Hoffmann leipzig.de. Universität Leipzig Ins?tut für Informa?k Technische Informa?

Informatik - Übungsstunde

6. Kontrollanweisungen II

Zeiger. Zeiger ist eine Variable deren Wert eine Adresse enthält. Zeiger werden im Programm definiert. int *pmyinteger; Type *PointerName ;

12. Felder (Arrays) II

Bereits behandelt: Einfache Datentypen / Variablen. Schleifen und Verzweigungen. Funktionen. Heute: Felder, Zeiger, Referenzen. Freispeicherverwaltung

Programmier-Befehle - Woche 08

6. Kontrollanweisungen II

Programmierkurs C++ Templates & STL (1/2)

Einführung Pointer. C-Kurs 2013, 2. Vorlesung. Nico Andy

3. Ganze Zahlen int unsigned int

12. Felder (Arrays) II

Programmierwerkstatt. Arrays, Pointer und Referenzen

8. Referenzen und Zeiger

Das erste C++ Programm

Zeiger (engl. Pointer)

Structs, Referenztypen und Const-Typen

2. Ganze Zahlen int unsigned int

Die Mersenne sche Vermutung. Einführung. Der Vortrag von Cole. Die Mersenne sche Vermutung

Praxis der Programmierung

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Zeiger & Co. Verwendung und Zeigerarithme5k. thorsten möller - informa5k.unibas.ch/lehre/fs13/cs109/03- c++- zeiger.pdf. Strukturen. enum.

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

Hello World! Eine Einführung in das Programmieren Variablen

17. Klassen. Datenkapselung, Klassen, Memberfunktionen, Konstruktoren

9. Vektoren. (auch Felder/array)

5.1 Mehr Basistypen. (Wie viele Werte kann man mit n Bit darstellen?)

Programmier-Befehle - Woche 9

DAP2 Praktikum Blatt 1

C++ Teil 5. Sven Groß. 12. Nov IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Einstieg in die Informatik mit Java

Bereits behandelt: Einfache Datentypen / Variablen. Schleifen und Verzweigungen. Funktionen. Heute: Felder, Zeiger, Referenzen. Freispeicherverwaltung

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Variablen in C++ Einfache Variablen Strukturen Arrays und Zeichenketten Zeiger und Referenzen Parameter Dynamische Speicherverwaltung

2.8 Klassen. Nichtgleichartige Elemente können in Klassen zu einem neuen Typ zusammengefasst werden. Beispiel: Die drei Komponenten

Zeiger (1) Allgemeines

1. Fliesskommazahlen

Transkript:

Felder (Arrays) und Zeiger (Pointers) - Teil I Feldtypen, Sieb des Eratosthenes, Iteration, Zeigertypen, Zeigerarithmetik, dynamische Speicherverwaltung

Felder: Motivation n Wir können jetzt über Zahlen iterieren: for (int i=0; i<n; ++i) {...}

Felder: Motivation n Wir können jetzt über Zahlen iterieren: for (int i=0; i<n; ++i) {...} n Oft muss man aber über Daten iterieren (Beispiel: finde ein Kino in Zürich, das heute The C++ Legacy zeigt)

Felder: Motivation n Wir können jetzt über Zahlen iterieren: for (int i=0; i<n; ++i) {...} n Oft muss man aber über Daten iterieren (Beispiel: finde ein Kino in Zürich, das heute The C++ Legacy zeigt) n Felder dienen zum Speichern von Folgen gleichartiger Daten (Beispiel: Spielpläne aller Zürcher Kinos)

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Streiche alle echten Vielfachen von 2...

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 9 11 13 15 17 Streiche alle echten Vielfachen von 2...

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 9 11 13 15 17...und gehe zur nächsten Zahl

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 9 11 13 15 17 Streiche alle echten Vielfachen von 3...

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 11 13 17 Streiche alle echten Vielfachen von 3...

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 11 13 17...und gehe zur nächsten Zahl

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen 2 3 5 7 11 13 17 Am Ende des Streichungsprozesses bleiben genau die Primzahlen übrig!

Felder: erste Anwendung Das Sieb des Eratosthenes o berechnet alle Primzahlen < n o Methode: Ausstreichen der Nicht- Primzahlen o Frage: wie streichen wir Zahlen aus??? mit einem Feld!

Felder: Implementierung Sieb des Eratosthenes int main() { const unsigned int n = 1000; Berechnet alle Primzahlen < 1000 // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,..., " << n-1 << "}:\n"; for (unsigned int i = 2; i < n; ++i) if (!crossed_out[i]) { // i is prime std::cout << i << " "; // cross out all proper multiples of i for (unsigned int m = 2*i; m < n; m += i) crossed_out[m] = true; } std::cout << "\n"; } return 0;

Felder: Implementierung Sieb des Eratosthenes int main() { const unsigned int n = 1000; // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,..., " << n-1 << "}:\n"; for (unsigned int i = 2; i < n; ++i) if (!crossed_out[i]) { // i is prime std::cout << i << " "; // cross out all proper multiples of i for (unsigned int m = 2*i; m < n; m += i) crossed_out[m] = true; } std::cout << "\n"; Berechnet alle Primzahlen < 1000 n ist eine Konstante, sollte also auch so deklariert werden! } return 0;

Felder: Implementierung Sieb des Eratosthenes int main() { const unsigned int n = 1000; // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,..., " << n-1 << "}:\n"; for (unsigned int i = 2; i < n; ++i) if (!crossed_out[i]) { // i is prime std::cout << i << " "; // cross out all proper multiples of i for (unsigned int m = 2*i; m < n; m += i) crossed_out[m] = true; } std::cout << "\n"; Feld: crossed_out[i] gibt an, ob i schon ausgestrichen wurde } return 0;

Felder: Implementierung Sieb des Eratosthenes int main() { const unsigned int n = 1000; // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,..., " << n-1 << "}:\n"; for (unsigned int i = 2; i < n; ++i) if (!crossed_out[i]) { // i is prime std::cout << i << " "; // cross out all proper multiples of i for (unsigned int m = 2*i; m < n; m += i) crossed_out[m] = true; } std::cout << "\n"; Das Sieb: gehe zur jeweils nächsten nichtgestrichenen Zahl i (diese ist Primzahl), gib sie aus und streiche alle echten Vielfachen von i aus } return 0;

Felder: Definition Deklaration einer Feldvariablen (array): T a [expr ] konstanter ganzzahliger Ausdruck; Wert gibt Länge des Feldes an Variable des Feld-Typs zugrundeliegender Typ

Felder: Definition Deklaration einer Feldvariablen (array): T a [expr ] Wert k ist bei Kompilierung bekannt (z.b. Literal, Konstante) konstanter ganzzahliger Ausdruck; Wert gibt Länge des Feldes an Variable des Feld-Typs zugrundeliegender Typ Typ von a : T [k ] Wertebereich von T [k ]: T k

Felder: Definition Deklaration einer Feldvariablen (array): T a [expr ] Wert k ist bei Kompilierung bekannt (z.b. Literal, Konstante) konstanter ganzzahliger Ausdruck; Wert gibt Länge des Feldes an Variable des Feld-Typs zugrundeliegender Typ Beispiel: bool crossed_out[n]

Felder variabler Länge? Praktischer wäre: int main() { // input of n std::cout << Compute prime numbers in [2, n) for n =? ; unsigned int n; std::cin >> n; } // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n];...

Felder variabler Länge? Praktischer (aber nicht erlaubt) wäre: int main() { // input of n std::cout << Compute prime numbers in [2, n) for n =? ; unsigned int n; std::cin >> n; } // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool crossed_out[n]; // Fehler!... kein konstanter Ausdruck!

Felder variabler Länge? Praktischer (und erlaubt) wäre: int main() { // input of n std::cout << Compute prime numbers in [2, n) for n =? ; unsigned int n; std::cin >> n; } // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[n-1] bool* const crossed_out = new bool[n]; // ok!... so geht es (Erklärung folgt)!

Feld-Initialisierung n int a[5]; Die 5 Elemente von a bleiben uninitialisiert (können später Werte zugewiesen bekommen)

Feld-Initialisierung n int a[5]; Die 5 Elemente von a bleiben uninitialisiert (können später Werte zugewiesen bekommen) n int a[5] = {4, 3, 5, 2, 1}; Die 5 Elemente von a werden mit einer Initialisierungsliste initialisiert

Feld-Initialisierung n int a[5]; Die 5 Elemente von a bleiben uninitialisiert (können später Werte zugewiesen bekommen) n int a[5] = {4, 3, 5, 2, 1}; auch ok; Länge wird deduziert Die 5 Elemente von a werden mit einer Initialisierungsliste initialisiert n int a[] = {4, 3, 5, 2, 1};

Speicherlayout eines Feldes o Ein Feld belegt einen zusammenhängenden Speicherbereich

Speicherlayout eines Feldes o Ein Feld belegt einen zusammenhängenden Speicherbereich Speicherzellen für jeweils einen Wert vom Typ T

Speicherlayout eines Feldes o Ein Feld belegt einen zusammenhängenden Speicherbereich Beispiel: Feld mit 4 Elementen Speicherzellen für jeweils einen Wert vom Typ T

Wahlfreier Zugriff (Random Access) Der L-Wert Wert i a [ expr ] hat Typ T und bezieht sich auf das i te Element des Feldes a (Zählung ab 0)

Wahlfreier Zugriff (Random Access) Der L-Wert Wert i a [ expr ] hat Typ T und bezieht sich auf das i te Element des Feldes a (Zählung ab 0) a[0] a[1] a[2] a[3]

Wahlfreier Zugriff (Random Access) a [ expr ] Der Wert i von expr heisst Feldindex []: Subskript-Operator

Wahlfreier Zugriff (Random Access) o Wahlfreier Zugriff ist sehr effizient: p : Adresse von a (das heisst: der ersten Speicherzelle von a) s : Speicherbedarf von T (in Zellen)

Wahlfreier Zugriff (Random Access) o Wahlfreier Zugriff ist sehr effizient (Reduktion auf Adressarithmetik): p : Adresse von a p + si : Adresse von a[i] s : Speicherbedarf von T (in Zellen) a[i]

Felder sind primitiv o Man kann Felder nicht wie bei anderen Typen initialisieren und zuweisen: int a[5] = {4,3,5,2,1}; int b[5]; b = a; // Fehler! int c[5] = a; // Fehler!

Felder sind primitiv o Man kann Felder nicht wie bei anderen Typen initialisieren und zuweisen: Warum? int a[5] = {4,3,5,2,1}; int b[5]; b = a; // Fehler! int c[5] = a; // Fehler!

Felder sind primitiv o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv

Felder sind primitiv o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv o In C, Felder sind sehr maschinennah und effizient, bieten aber keinen Luxus wie eingebautes Initialisieren und Kopieren

Felder sind primitiv o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv o In C, Felder sind sehr maschinennah und effizient, bieten aber keinen Luxus wie eingebautes Initialisieren und Kopieren o Die Standard-Bibliothek bietet komfortable Alternativen (mehr dazu später)

Felder als Daten-Container Container: o Objekt, das andere Objekte speichern kann

Felder als Daten-Container Container: o Objekt, das andere Objekte speichern kann... o...und die Möglichkeit anbietet, über die gespeicherten Objekte zu iterieren (Kinoprogramme...)

Felder als Daten-Container Container: o Objekt, das andere Objekte speichern kann... o...und die Möglichkeit anbietet, über die gespeicherten Objekte zu iterieren (Kinoprogramme...) Iteration in Feldern geht über wahlfreien Zugriff: a[0], a[1],...,a[n-1]

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand: p 0 s Zellen crossed_out 999

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand (Adressberechnung): p+s 0 s Zellen crossed_out 999

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand (Adressberechnung): p+2s 0 s Zellen crossed_out 999

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand (Adressberechnung): p+3s 0 s Zellen crossed_out 999

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand (Adressberechnung): p+999s 0 s Zellen crossed_out 999

Iteration durch wahlfreien Zugriff for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnungsaufwand (Adressberechnung): Pro Feldelement eine Addition und eine Multiplikation p + i s 0 s Zellen crossed_out 999

Effizientere und natürlichere Iteration p p+s p+2s Addieren von s: gehe zum nächsten Element p+999s 0 s Zellen crossed_out 999

Effizientere und natürlichere Iteration Berechnungsaufwand (Adressberechnung): Pro Feldelement eine Addition p vorher + s 0 s Zellen crossed_out 999

Effizientere und natürlichere Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p Pro Feldelement eine Addition p vorher + s 0 s Zellen crossed_out 999

Effizientere und natürlichere Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + 1000;// ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) wird noch genau erklärt! *p = false; // *p is the element pointed to by p Pro Feldelement eine Addition p vorher + s 0 s Zellen crossed_out 999

Buchlesen: Wahlfreier Zugriff vs. natürliche Iteration Wahlfreier Zugriff: o öffne Buch auf S.1 o o o o klappe Buch zu öffne Buch auf S.2-3 klappe Buch zu öffne Buch auf S.4-5 o... Natürliche Iteration: o öffne Buch auf S.1 o o o o blättere um blättere um blättere um blättere um o...

Zeiger o erlauben das Repräsentieren von und das Rechnen mit Adressen

Zeiger o erlauben das Repräsentieren von und das Rechnen mit Adressen o unterstützen insbesondere die Operation gehe zum nächsten Element eines Feldes

Zeiger o erlauben das Repräsentieren von und das Rechnen mit Adressen o unterstützen insbesondere die Operation gehe zum nächsten Element eines Feldes o sind mit Vorsicht zu verwenden (beim Verrechnen mit Adressen stürzt meist das Programm ab)

Zeiger-Typen T * sprich: Zeiger auf T zugrundeliegender Typ o T * hat als mögliche Werte Adressen von Objekten des Typs T

Zeiger-Typen T * sprich: Zeiger auf T zugrundeliegender Typ o T * hat als mögliche Werte Adressen von Objekten des Typs T o Ausdrücke vom Typ T * heissen Zeiger

Zeiger: Visualisierung p Zeiger auf das Objekt (Wert von p ist die Adresse des Objekts) Objekt im Speicher

Adressoperator o liefert einen Zeiger (R-Wert) auf ein beliebiges Objekt, gegeben durch einen L-Wert & L-Wert

Adressoperator o liefert einen Zeiger (R-Wert) auf ein beliebiges Objekt, gegeben durch einen L-Wert & L-Wert int i = 5; int* iptr = &i; iptr i &

Dereferenzierungsoperator o liefert einen L-Wert für ein Objekt, gegeben durch einen Zeiger auf das Objekt * R-Wert

Dereferenzierungsoperator o liefert einen L-Wert für ein Objekt, gegeben durch einen Zeiger auf das Objekt * R-Wert int i = 5; int* iptr = &i; int j = *iptr; // j = 5 iptr i *

Dereferenzierungsoperator = Adressoperator -1 Zeiger (R-Wert) & * Objekt (L-Wert)

Felder sind Zeiger o Jedes Feld vom Typ T [k] ist in den Typ T* konvertierbar Feld-nach-Zeiger-Konversion

Felder sind Zeiger o Jedes Feld vom Typ T [k] ist in den Typ T* konvertierbar Feld-nach-Zeiger-Konversion o Ergebnis der Konversion ist ein Zeiger auf das erste Element (Feldindex 0)

Felder sind Zeiger o Jedes Feld vom Typ T [k] ist in den Typ T* konvertierbar Feld-nach-Zeiger-Konversion o Ergebnis der Konversion ist ein Zeiger auf das erste Element (Feldindex 0) o Tritt ein Feld in einem Ausdruck auf, so wird es automatisch konvertiert Im Rechner passiert dabei nichts: ein Feld ist ohnehin nur durch die Adresse des ersten Elements repräsentiert.

Felder sind Zeiger Beispiel: int a[5]; int* begin = a; begin a

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger p : Zeiger auf ein Feldelement a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger...oder auf Zelle direkt hinter dem Feld (past-the-end Zeiger) p a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger p - 2 p - 1 p p + 1 p + 2 p + 3 p + 4 a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger Addenden mit Ergebniszeiger ausserhalb dieses Bereichs sind illegal! p - 2 p - 1 p p + 1 p + 2 p + 3 p + 4 a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger p +=, -=, ++, -- gibt es auch, mit der üblichen Bedeutung a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger q < p == p < r < s a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger!= : nicht == q < p == p < r <= : < oder == > : nicht <= >= : nicht < a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger -2 q p r s a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger -2 q p r s a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger -1 q p r s a[0] a[1] a[2] a[3] a[4] a[5]

Zeiger-Arithmetik o Zeiger {+, -} ganze Zahl o Zeiger {==,!=, <, >, <=, >=} Zeiger o Zeiger - Zeiger -1 q p r r p = 2 p q = 1 r q = 3 a[0] a[1] a[2] a[3] a[4] a[5]

Die Wahrheit über den Subskript-Operator o arbeitet eigentlich auf Zeigern: a [ expr ] ist eine Abkürzung für * (a + expr )

Die Wahrheit über den Subskript-Operator o arbeitet eigentlich auf Zeigern: a [ expr ] ist eine Abkürzung für * (a + expr ) Bespiel: expr hat Wert 2 a[0] a[1] a[2] a[3] a[4] a[5]

Die Wahrheit über den Subskript-Operator o arbeitet eigentlich auf Zeigern: a [ expr ] ist eine Abkürzung für * (a + expr ) Bespiel: expr hat Wert 2 a[0] a[1] a[2] a[3] a[4] a[5]

Iteration durch Zeiger bool* const begin = crossed_out; //ptr to first element bool* const end = crossed_out + 1000; //ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) wird noch genau erklärt! *p = false; // *p is the element pointed to by p

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin Feld-nach-Zeiger-Konversion 0 s Zellen crossed_out n-1

Iteration durch Zeiger begin ist eine Konstante! bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin Feld-nach-Zeiger-Konversion 0 s Zellen crossed_out n-1

Iteration durch Zeiger const bool* begin wäre ein variabler Zeiger auf const bool! bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin Feld-nach-Zeiger-Konversion 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin Feld-nach-Zeiger-Konversion end Zeiger + ganze Zahl 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeiger-Initialisierung end 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeiger-Vergleich end 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Dereferenzierung, Zuweisung end false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeigerinkrement end false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeiger-Vergleich end false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Dereferenzierung, Zuweisung end false false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeigerinkrement, usw... end false false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p...usw., Zeigerinkrement end false false false false false false false false false false false false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin p Zeiger-Vergleich end false false false false false false false false false false false false 0 s Zellen crossed_out n-1

Iteration durch Zeiger bool* const begin = crossed_out; // ptr to first element bool* const end = crossed_out + n; // ptr after last element // in the loop, pointer p successively points to all elements for (bool* p = begin; p!= end; ++p) *p = false; // *p is the element pointed to by p begin fertig! end false false false false false false false false false false false false 0 s Zellen crossed_out n-1

Warum Zeiger? o Die (geringfügig) schnellere Iteration ist nicht der Punkt (Lesbarkeit spricht oft eher für wahlfreien Zugriff)

Warum Zeiger? o Die (geringfügig) schnellere Iteration ist nicht der Punkt (Lesbarkeit spricht oft eher für wahlfreien Zugriff) o Grund 1: wir brauchen sie für Felder mit variabler Länge (gleich...)

Warum Zeiger? o Die (geringfügig) schnellere Iteration ist nicht der Punkt (Lesbarkeit spricht oft eher für wahlfreien Zugriff) o Grund 1: wir brauchen sie für Felder mit variabler Länge (gleich...) o Grund 2: std:: Container-Algorithmen (Sortieren,...) brauchen Iteratoren

Warum Zeiger? o Die (geringfügig) schnellere Iteration ist nicht der Punkt (Lesbarkeit spricht oft eher für wahlfreien Zugriff) o Grund 1: wir brauchen sie für Felder mit variabler Länge (gleich...) o Grund 2: std:: Container-Algorithmen (Sortieren,...) brauchen Iteratoren Zeiger sind die Iteratoren der Felder!

Dynamischer Speicher o wie besorgen wir Speicher, der bei Kompilierung nicht vorhersehbar ist?

Dynamischer Speicher o wie besorgen wir Speicher, der bei Kompilierung nicht vorhersehbar ist? o o Sieb des Eratosthenes mit Eingabe von n Allgemein: Feld variabler Länge

New-Ausdrücke new T Ausdruck vom Typ T * (Zeiger) new-operator

New-Ausdrücke new T Ausdruck vom Typ T * (Zeiger) new-operator o Effekt: neuer Speicher für ein Objekt vom Typ T wird bereitgestellt; der Wert des Ausdrucks ist dessen Adresse

New-Ausdrücke new T [expr ] Ausdruck vom Typ T * (Zeiger) new-operator Typ int, Wert n ; expr nicht notwendigerweise konstant o Effekt: neuer Speicher für ein Feld der Länge n mit zugrundeliegendem Typ T wird bereitgestellt; Wert des Ausdrucks ist Adresse des ersten Elements

Der Heap o Hauptspeicherbereich, aus dem das Programm neuen Speicher holen kann. heap ( dynamischer Speicher )

Der Heap o Hauptspeicherbereich, aus dem das Programm neuen Speicher holen kann. int* i = new int; heap ( dynamischer Speicher )

Der Heap o Hauptspeicherbereich, aus dem das Programm neuen Speicher holen kann. int* i = new int; int* a = new int[3]; heap ( dynamischer Speicher )

Sieb des Eratosthenes bisher: statischer Speicher int main() { const unsigned int n = 1000; bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output... } return 0;

Sieb des Eratosthenes neu: dynamischer Speicher int main() { const unsigned int n = 1000; int main() { // input std::cout << "Compute prime numbers in {2,...,n-1} for n =? "; unsigned int n; std::cin >> n; bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; bool* crossed_out = new bool[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output... // computation and output... delete[] crossed_out; } return 0; } return 0;

Sieb des Eratosthenes neu: dynamischer Speicher int main() { const unsigned int n = 1000; int main() { // input std::cout << "Compute prime numbers in {2,...,n-1} for n =? "; unsigned int n; std::cin >> n; bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; bool* crossed_out = new bool[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; // computation and output... // computation and output... delete[] crossed_out; } return 0; Subskript-Operator auf Zeiger crossed_out } return 0;

Sieb des Eratosthenes neu: dynamischer Speicher int main() { const unsigned int n = 1000; int main() { // input std::cout << "Compute prime numbers in {2,...,n-1} for n =? "; unsigned int n; std::cin >> n; bool crossed_out[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; bool* crossed_out = new bool[n]; for (unsigned int i = 0; i < n; ++i) crossed_out[i] = false; } // computation and output... return 0; Freigabe des nicht mehr benötigten dynamischen Speichers } // computation and output... delete[] crossed_out; return 0;

Delete-Ausdrücke Mit new erzeugte Objekte haben dyna- mische Speicherdauer: sie leben, bis sie explizit gelöscht werden: delete expr delete-operator Zeiger vom Typ T *, der auf ein vorher mit new bereitgestelltes Objekt zeigt; Effekt: Speicher auf dem Heap wird wieder freigegeben.

Delete-Ausdrücke Mit new erzeugte Objekte haben dynamische Speicherdauer: sie leben, bis sie explizit gelöscht werden: int* i = new int; delete expr... delete i; delete-operator Zeiger vom Typ T *, der auf ein vorher mit new bereitgestelltes Objekt zeigt; Effekt: Speicher auf dem Heap wird wieder freigegeben.

Delete-Ausdrücke Mit new erzeugte Objekte haben dyna- mische Speicherdauer: sie leben, bis sie explizit gelöscht werden. delete[] expr delete-operator Zeiger vom Typ T *, der auf ein vorher mit new bereitgestelltes Feld zeigt; Effekt: Speicher auf dem Heap wird wieder freigegeben.

Delete-Ausdrücke Mit new erzeugte Objekte haben dynamische Speicherdauer: sie leben, bis sie explizit gelöscht werden. int* a = new int[3]; delete[] expr... delete[] a; delete-operator Zeiger vom Typ T *, der auf ein vorher mit new bereitgestelltes Feld zeigt; Effekt: Speicher auf dem Heap wird wieder freigegeben.

Dynamische-Speicher- Richtlinie Zu jedem new gibt es ein passendes delete int* a = new int[3];

Dynamische-Speicher- Richtlinie Zu jedem new gibt es ein passendes delete int* a = new int[3];... delete[] a;

Dynamische-Speicher- Richtlinie Zu jedem new gibt es ein passendes delete Nichtbefolgung führt zu Speicherlecks (ungenutzter, aber nicht mehr verfügbarer Speicher auf dem Heap)