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

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

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

Dynamische Datentypen

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

Crashkurs C++ - Teil 1

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

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

Algorithmen und Datenstrukturen

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

Programmierung mit C Zeiger

Zeiger: Der Adressoperator &

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

Einführung in die Programmiersprache C

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

1. Referenzdatentypen: Felder und Strings

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

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

Das erste C++ Programm

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

Grundlagen der Informatik 11. Zeiger

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Referenzen. Referenzen

Structs, Referenztypen und Const-Typen

DAP2 Praktikum Blatt 1

3. Wahrheitswerte. Boolesche Funktionen; der Typ bool; logische und relationale Operatoren; Kurzschlussauswertung; Assertions und Konstanten

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

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

Angewandte Mathematik und Programmierung

2. Programmierung in C

2.7 Felder (Arrays) Das englische Wort array hatte ursprünglich militärische Bedeutung: Aufstellung zur Schlacht : Titel der Zeichnung links:

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

8. Referenzen und Zeiger

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

Einstieg in die Informatik mit Java

Institut für Programmierung und Reaktive Systeme. Java 2. Markus Reschke

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

F Zeiger, Felder und Strukturen in C

Programmierkurs C++ Variablen und Datentypen

Lindenmayer-Systeme: Fraktale rekursiv zeichnen. Definition. Definition. Definition. o Alphabet Σ ( Beispiel: {F, +, -} )

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

Wertebereich und Genauigkeit der Zahlendarstellung

Advanced Programming in C

1 Aufgaben 1.1 Objektorientiert: ("extended-hamster") Sammel-Hamster

Modellierung und Programmierung 1

Grundlagen der Informatik 2. Typen

Grundlagen der Informatik 6. Arrays I

Programmieren I. Kapitel 5. Kontrollfluss

Vorlesung Programmieren

Container für eine Folge gleichartiger Daten. Dynamische Datentypen. Probleme mit Feldern...aber nicht mit std::vector. ... und auch std::vector

Zeiger und dynamischer Speicher

Felder (1) Allgemeines

Grundlagen der Informatik 2. Operatoren

Zeiger. C-Kurs 2012, 2. Vorlesung. Tino Kutschbach 10.

C-Pointer (Zeiger, Adressen) vs. C++ Referenzen

Praxisorientierte Einführung in C++ Lektion: "Dynamische Speicherverwaltung"

Informatik I (D-ITET)

Was Mathematiker schon vor Jahrhunderten erfunden haben, gibt es jetzt endlich in ihrer Programmiersprache:

Martin Unold INFORMATIK. Geoinformatik und Vermessung

Informatik I (D-MAVT)

Einführung in die Programmierung II. 5. Zeiger

Lindenmayer-Systeme: Fraktale rekursiv zeichnen

RO-Tutorien 3 / 6 / 12

1 Klassen und Objekte

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

Das folgende Programm demonstriert, wie man Speicheradressen von Variablen ermittelt.

VDK-Informatik

4 Kontrollfluss-Diagramme

float: Fließkommazahl nach IEEE 754 Standard mit 32 bit

Kapitel 4. Programmierkurs. Datentypen. Arten von Datentypen. Wiederholung Kapitel 4. Birgit Engels, Anna Schulze WS 07/08

Speicher und Adressraum

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Vorlesung Programmieren

Zeiger, Arrays und Strings in C und C++

II. Grundlagen der Programmierung. Beispiel: Merge Sort. Beispiel: Merge Sort (Forts. ) Beispiel: Merge Sort (Forts. )

Einführung. Die Mersenne sche Vermutung, Editor, Compiler, Computer, Betriebssystem, Plattform, Das erste C++-Programm

Variablen. int Flugzeug. float. I write code Hund. String. long. Borchers: Programmierung für Alle (Java), WS 06/07 Kapitel

Vorkurs C++ Programmierung

C- Kurs 07 Höhere Datentypen

Dr. Monika Meiler. Inhalt

Algorithmen implementieren. Implementieren von Algorithmen

Teil 5: Zeiger, Felder, Zeichenketten Gliederung

Projekt 3 Variablen und Operatoren

C/C++-Programmierung

Einführung. Programmieren, Die Mersenne sche Vermutung, Editor, Compiler, Computer, Betriebssystem, Plattform, Das erste C++ Programm

Kontrollfluss. Kontrollanweisungen. if-anweisung. if-else Anweisung. else. Auswahlanweisungen, Iterationsanweisungen, Blöcke, Sprunganweisungen

Typisierung. Prüfungen zur Übersetzungszeit Type Test und Type Cast Bedingte Zuweisung Nil Übergangsparameter Grade der Typisierung. 3.

Tag 4 Repetitorium Informatik (Java)

Kapitel 3: Variablen

einlesen n > 0? Ausgabe Negative Zahl

Java I Vorlesung Imperatives Programmieren

Hier wird die Verwendung der Standard Template Library (kurz STL) kurz beschrieben. Inhalt 1.Verwendung der STL Grundlagen...

8 Zugriffstypen ( Zeiger )

Programmier-Befehle - Woche 10

Operatoren (1) Operatoren (2)

Algorithmen und Datenstrukturen (für ET/IT) Wiederholung: Ziele der Vorlesung. Wintersemester 2012/13. Dr. Tobias Lasser

Transkript:

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

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

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

Felder: Motivation Wir können jetzt über Zahlen iterieren: for (int i=0; i<n; ++i) {...} Oft muss man aber über Daten iterieren (Beispiel: finde ein Kino in Zürich, das heute The C++ Ultimatum zeigt) 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() { // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[999] bool crossed_out[1000]; for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; Berechnet alle Primzahlen < 1000 // computation and output std::cout << "Prime numbers in {2,...,999}:\n"; for (unsigned int i = 2; i < 1000; ++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 < 1000; m += i) crossed_out[m] = true; } std::cout << "\n"; } return 0;

Felder: Implementierung Sieb des Eratosthenes int main() { // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[999] bool crossed_out[1000]; for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,...,999}:\n"; for (unsigned int i = 2; i < 1000; ++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 < 1000; m += i) crossed_out[m] = true; } std::cout << "\n"; Berechnet alle Primzahlen < 1000 Feld: crossed_out[i] gibt an, ob i schon ausgestrichen wurde } return 0;

Felder: Implementierung Sieb des Eratosthenes int main() { // definition and initialization: provides us with // Booleans crossed_out[0],..., crossed_out[999] bool crossed_out[1000]; for (unsigned int i = 0; i < 1000; ++i) crossed_out[i] = false; // computation and output std::cout << "Prime numbers in {2,...,999}:\n"; for (unsigned int i = 2; i < 1000; ++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 < 1000; m += i) crossed_out[m] = true; } std::cout << "\n"; Berechnet alle Primzahlen < 1000 Feld: crossed_out[i] gibt an, ob i schon ausgestrichen wurde 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) 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) konstanter ganzzahliger Ausdruck; Wert gibt Länge des Feldes an Variable des Feld-Typs zugrundeliegender Typ Beispiel: bool crossed_out[1000]

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* crossed_out = new bool[n]; // ok!... so geht es (Erklärung folgt)!

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

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

Feld-Initialisierung int a[5]; Die 5 Elemente von a bleiben uninitialisiert (können später Werte zugewiesen bekommen) int a[5] = {4, 3, 5, 2, 1}; auch ok; Länge wird deduziert Die 5 Elemente von a werden mit einer Initialisierungsliste initialisiert 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) Die Deklaration T a [expr ] kann man deshalb auch lesen als a [expr ] ist vom Typ T

Wahlfreier Zugriff (Random Access) Die Deklaration T a [expr ] implizite Definition des Typs von a kann man deshalb auch lesen als a [expr ] ist vom Typ T

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]

Wahlfreier Zugriff (Random Access) Warnung: Die Länge n eines Feldes kann nicht abgefragt werden, man muss sie wissen. Für jeden Feldindex i muss 0 i < n gelten, andernfalls ist das Programmverhalten undefiniert!

Felder sind nicht selbstbeschreibend 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 nicht selbstbeschreibend 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 nicht selbstbeschreibend o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv

Felder sind nicht selbstbeschreibend o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv o Ein Feld merkt sich nur die Adresse des ersten Elements o o kein Problem bei Random Access, aber beim Initialisieren / Zuweisen ist dann nicht klar, wieviele Elemente kopiert werden müssen

Felder sind nicht selbstbeschreibend o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv o Ein Feld merkt sich nur die Adresse des ersten Elements o o kein Problem bei Random Access, aber beim Initialisieren / Zuweisen ist dann nicht klar, wieviele Elemente kopiert werden müssen int a[5] = {4,3,5,2,1}; int b[5]; b = a; // wieviele Elemente haben a und b nochmal?

Felder sind nicht selbstbeschreibend o Felder sind Erblast der Sprache C und aus heutiger Sicht primitiv o Ein Feld merkt sich nur die Adresse des ersten Elements bei legalen Indizes! o o kein Problem bei Random Access, aber beim Initialisieren / Zuweisen ist dann nicht klar, wieviele Elemente kopiert werden müssen int a[5] = {4,3,5,2,1}; int b[5]; b = a; // wieviele Elemente haben a und b nochmal?

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 (z.b. Kinospielpläne...) 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: 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: 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: 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: 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: 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: Pro Feldelement eine Addition p vorher + s 0 s Zellen crossed_out 999

Effizientere und natürlichere Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 &

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 & Kann man lesen als int *iptr = &i (d.h. *iptr ist vom Typ int ). Wieder ein Fall von impliziter Typdefinition!

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)

Nichtinitialisierte Zeiger o sind eine typische Fehlerquelle

Nichtinitialisierte Zeiger o sind eine typische Fehlerquelle int* iptr; // nicht initialisiert... int j = *iptr; // Objekt an "zufaelliger Adresse // --> undefiniertes Verhalten

Nullzeiger o Zeiger, die (noch) nicht auf ein Objekt zeigen, sollten mit 0 initialisiert werden int* iptr = 0; // Nullzeiger... int j = *iptr; // kein Objekt an dieser Adresse // --> "sicherer Laufzeitfehler

Nullzeiger o Zeiger, die (noch) nicht auf ein Objekt zeigen, sollten mit 0 initialisiert werden int* iptr = 0; // Nullzeiger... if (iptr!= 0) { // so ist s am besten int j = *iptr;... }

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

Felder sind Zeiger Beispiel: int a[5]; int* begin = a; Ist das äquivalent zu begin a int a[5]; int* begin = &a[0];?

Felder sind Zeiger Beispiel: int a[5]; int* begin = a; Ist das äquivalent zu begin int a[5];? int* begin = &a[0]; a Nicht ganz, denn hier wird zusätzlich noch a[0] ausgewertet!

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* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 Feld-nach-Zeiger-Konversion begin Zeiger + ganze Zahl end 0 s Zellen crossed_out 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

Iteration durch Zeiger bool* begin = crossed_out; // pointer to first element bool* end = crossed_out + 1000; // pointer 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 999

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 Grund1: 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 Grund1: 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 Grund1: 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 Speichers holen kann. heap ( dynamischer Speicher )

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

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

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

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

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

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

Delete-Ausdrücke Mit new erzeugte Objekte haben dynamische 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: delete expr int* i = new int;... 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 dynamische 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. delete[] expr int* a = new int[3];... 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)