Zeiger (1) Allgemeines

Ähnliche Dokumente
2. Programmierung in C

F Zeiger, Felder und Strukturen in C

Zeiger (engl. Pointer)

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

Teil 5: Felder, Zeiger, Zeigerarithmetik Gliederung

Felder, Zeiger und Adreßrechnung

Teil 5: Zeiger, Felder, Zeichenketten Gliederung

Praxis der Programmierung

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

Vorkurs Informatik WiSe 16/17

6. Zeiger Allgemeines Definition eines Zeigers

Programmierung mit C Zeiger

Felder (1) Allgemeines

Vorkurs Informatik WiSe 17/18

Pointer und Arrays. INE1, Montag M. Thaler, Office TG208. ZHAW, M. Thaler, K. Rege, G.

Ausdrücke (1) Grundlegende Eigenschaften

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

Kapitel 4: Zeiger. Inhalt. Zeiger Zeigerarithmetik

8. Referenzen und Zeiger

Einführung in die Programmierung II. 5. Zeiger

6 ZEIGER UND REFERENZEN - ALLGEMEINES

Praxis der Programmierung

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

2. Programmierung in C

INE1 Arrays, Zeiger, Datenstrukturen

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

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

Probeklausur Name: (c)

Informatik Vorkurs - Vorlesung 2

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

U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Besprechung Aufgabe 1. Pointer. Register und Ports. SPiC - Ü U3.1

Kapitel 8. Adressen und Zeiger

Ausdrücke in C. Ein großes Teilgebiet der Sprache C im Zusammenhang von Dieter Holzhäuser

7 Funktionen. 7.1 Definition. Prototyp-Syntax: {Speicherklasse} {Typ} Name ({formale Parameter});

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

C-Programmierung: Ausdrücke und Operatoren#Division.2F

Betriebssysteme, Rechnernetze und verteilte Systeme 1. Crashkurs C (2)

Zeiger: Der Adressoperator &

C/C++-Programmierung

Variablen. CoMa-Übung VIII TU Berlin. CoMa-Übung VIII (TU Berlin) Variablen / 15

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

Datei: svn/ckurs/trunk/c_texte/c_arrptr.txt, Datum: 30. Juni Felder und Zeiger

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

Strukturen in C. Strukturen stellen eine Zusammenfassung von Datenelementen unterschiedlichen Typs unter einem Namen dar.

Die Sprache C# Datentypen, Speicherverwaltung Grundelemente der Sprache. Dr. Beatrice Amrhein

K Ergänzungen zur Einführung in C

Physische Datenstrukturen

10.4 Konstante Objekte

Repetitorium Programmieren I + II

Zeiger, Arrays und Strings in C und C++

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

Viel Erfolg bei der Bearbeitung der Aufgaben!

9. Vektoren. (auch Felder/array)

magnum C++ WALTER SAUMWEBER kompakt komplett kompetent

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

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

Kapitel 3: Variablen

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

Hello World! Eine Einführung in das Programmieren Variablen

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

Felder fester Länge (1)

Informatik. Wiederholung Felder (Arrays), string. Vorlesung

Programmieren in C. Zeiger und Zeichenketten. Prof. Dr. Nikolaus Wulff

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

3. Operatoren und Ausdrücke

Eine praktische Einführung in die Programmierung mit der Programmiersprache C

Inhalt. 1 Einstieg in die Welt von C Erste Schritte in C 31. Vorwort... 15

Speicherklassen (1) Lokale Variablen

Angewandte Mathematik und Programmierung

Dynamischer Speicher

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

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

5.4 Arrays. Oft müssen viele Werte gleichen Typs gespeichert werden. Idee: Lege sie konsekutiv ab! Greife auf einzelne Werte über ihren Index zu!

JAVA-Datentypen und deren Wertebereich

Arrays. Theorieteil. Inhaltsverzeichnis. Begriffe. Programmieren mit Java Modul 3. 1 Modulübersicht 3

Arrays (Felder/Vektoren)

3. Operatoren und Ausdrücke

3. Operatoren und Ausdrücke

C++ - Objektorientierte Programmierung Konstante und statische Elemente

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

Javaprogrammierung mit NetBeans. Variablen, Datentypen, Methoden

Grundlagen und Konzepte von C Datenstrukturen

PROCESSING EINE ZUSAMMENFASSUNG. Created by Michael Kirsch & Beat Rossmy

Einstieg in die Informatik mit Java

Programmierwerkstatt. Arrays, Pointer und Referenzen

einlesen n > 0? Ausgabe Negative Zahl

Die Sprache C# Datentypen, Speicherverwaltung Grundelemente der Sprache. Dr. Beatrice Amrhein

Grundlagen der Informatik 2. Operatoren

Organisatorisches. Folien (u.a.) gibt's auf der Lva-Homepage zum Download

Projekt 3 Variablen und Operatoren

Transkript:

Zeiger (1) Allgemeines In C häufig verwendet zur Realisierung mancher Programmierkonzepte Sehr enge Verknüpfung von Zeigern und Feldern Vielseitiges Hilfsmittel, birgt allerdings auch Gefahren für Programmierfehler Symbolisches Beispiel: Visitenkarte ist Zeiger auf Wohnort einer Person Technisch ist ein Zeiger eine Variable mit einer Adresse als Inhalt ptr v Ptr ist die Zeigervariable, die die Adresse der variable v beinhaltet und somit auf diese zeigt: ptr v 500 9 300 500

Zeiger (2) Allgemeines Woher weiß man, wo Variable im Speicher steht? Adressoperator & ptr = &v; Adresse der Variablen v wird ptr zugewiesen Der Programmierer muss nicht wissen, wo v tatsächlich im Speicher steht Ptr zeigt auf v: ptr v 9 Adressoperator kann nur auf Lvalues angewendet werden, nicht auf Ausdrücke, Konstanten oder Register-Variablen

Zeiger (3) Allgemeines Will man das Objekt erreichen, auf den ein Zeiger zeigt, muss man den unären Inhaltsoperator * dem Zeiger vorangestellt werden *ptr = 3; dem Objekt, auf das ptr zeigt, wird der Wert 3 zugewiesen Die Operatoren * und & kehren einander um, also ist *&v äquivalent zu v und &*ptr ist äquivalent zu ptr Zeiger werden wie folgt definiert: Typ *Zeiger; Damit gibt es noch keinen Ort und keinen Speicherplatz für die Variable, sondern nur einen Zeiger, der auf eine Variable zeigen kann Analogie: eine Visitenkarte zeigt die Adresse einer Person, das Stück Papier ist jedoch nicht die Person selbst Zeiger haben einen Datentyp, auf den sie zeigen. Beispiel: long *ptr;

Zeiger (4) Allgemeines Demonstrationsbeispiel: long *ptr; long v; long feld[3]; v = 0; ptr = &v; // Zeige auf v *ptr = 5; // Überschreibe Objekt, auf das ptr zeigt, mit 5 feld[0] = 2; ptr = &feld[0]; // Setze Adresse von feld[0] *ptr = 3; // Überschreibe Objekt, auf das ptr zeigt, mit 3 Normalerweise würde man hier vereinfacht wie folgt implementieren: v = 5; // Überschreibt v mit 5 feld[0] = 3; // Überschreibt feld[0] mit 3

Zeiger (5) Allgemeines Zeiger, die auf kein Objekt zeigen, sind ungültig Um das auszusagen, lässt man sie auf 0 zeigen Auf Adresse 0 befindet sich das Betriebssystem und darauf darf nicht zugegriffen werden Zum Prüfen der Gültigkeit eines Zeigers vergleicht man sie mit 0 long feld[3]; long *ptr = &feld[0]; // ptr ist gesetzt // ptr darf verwendet werden //... ptr = 0; // ptr ist ungültig! // ptr darf nicht mehr verwendet werden! //...

Zeiger (6) Allgemeines Zeiger sind Variablen, man kann mit ihnen auch genauso arbeiten long a; long *ap, *ptr; ap = &a; ptr = ap; ap und ptr zeigen auf die gleiche Adresse, man kann also das gleiche Objekt bearbeiten Man kann mit Zeigern auch rechnen: ptr = ptr + 1; Da Zeiger in C typisiert sind (z.b. long), zeigt der Zeiger nach der Operation auf das nachfolgende Element im Speicher dahinter (vorausgesetzt, da steht auch etwas Sinnvolles drin)

Zeiger (7) Zeiger als Parameter Funktionen liefern nur einen Ergebniswert zurück Sollen mehrere Ergebnisse zurückgegeben werden, müssen Zeiger als Parameter verwendet werden Zeiger zeigen dann auf die Originaldaten, die Zeiger selbst sind dann eine lokale Kopie der Originalzeiger und nur innerhalb der Funktion sichtbar void SwapLong(long *x, long *y) { long h; // Dreieckstausch h = *x; *x = *y; *y = h; } // end SwapLong Aufruf der Funktion: long a, b; SwapLong(&a, &b);

Zeiger (8) Zeiger als Parameter void MinimumSuche(long feld[], long len) { long i, j, min; for (j = 0; j < len; j = j + 1) { // Suche das Minimum // Minimum vor Suchbeginn bei Index 0 min = j; for (i = j + 1; i < len; i = i + 1) if (feld[i] < feld[min]) min = i; // Tausche SwapLong(&feld[j], &feld[min]); } } // end Minimum Funktion SwapLong kann Variablen des Feldes nicht sehen Übergebene Adressen erlauben Zugriff auf die zu tauschenden Elemente

Zeiger (9) Zeiger und Felder Ein Feld ist ein Verbundtyp von Variablen und steht in einem zusammenhängenden Bereich im Speicher Name des Feldes ist ein konstanter Zeiger, der auf die Anfangsadresse des Feldes zeigt Adressen von Feldnamen kann man nicht verändern: long feld[10]; long *ptr; ptr = feld; // Gültig, aber schlechter Programmierstil! feld = ptr; // Fehler! Die Adresse des Feldes ist nicht veränderbar! Leichter zu lesen ist folgender Ausdruck, der die Adresse des ersten Feldelementes zuweist: ptr = &feld[0]; ptr feld

Zeiger (10) Zeiger und Felder Vorteil von Zeigern ist ihre Flexibilität Zum Austausch von Feldern müsste man eigentlich elementweise austauschen Mit Zeigern geht das einfacher: long feld1[10]; long feld2[10]; ptr1 = &feld1[0]; ptr2 = &feld2[0]; ptr2 = &feld1[0]; // die Zeiger werden ausgetauscht zugewiesen ptr1 = &feld2[0]; Entsprechend kann man eine Swap-Funktion schreiben, die den Austausch der Zeiger realisiert

Zeiger (11) Zeigerarithmetik long feld[10]; // Feld mit 10 Elementen vom Typ long long *ptr; // Zeiger auf long ptr = &feld[0]; // ptr zeigt jetzt auf das erste Feldelement Folgende sind Ausdrücke dem Wert nach äquivalent: &feld[0] // Adresse von Felselement 0 ptr Es gilt dann auch folgendes: &feld[n] ptr + n // Adresse von Felselement n // Zeiger um n long-größen erhöhen Erhöhung des Zeigers um 1 bewirkt auch Erhöhung der Adresse um die Größe des Objektes, auf den er zeigt (Dualität Zeiger / Feld) Man kann also mit Zeigern rechnen: ptr = ptr + 1; // Adresse des nächsten long-elementes zuweisen

Zeiger (12) Zeigerarithmetik: Addition Veranschaulichung der Operation ptr = ptr + 1;: ptr feld Die Adressrechnung kann man mit Formeln wie folgt ausdrücken: AA pppppp+1 = AA pppppp + nn DDDDDDDDDDDDDDDD mit nn DDDDDDDDDDDDDDDD = sizeof DDDDDDDDDDDDDDDD Der Datentyp kann beliebig sein (auch benutzerdefiniert) Eine long-variable umfasst auf 32-Bit-Rechnerarchitekturen 4 Bytes, also wird die tatsächliche Adresse des Zeigers um 4 Bytes erhöht Zeigte z.b. der Zeiger vor der Operation auf Adresse 2000 hex, so zeigt er nach der Operation auf Adresse 2004 hex.

Zeiger (13) Zeigerarithmetik: Subtraktion, Vergleiche Will man feststellen, wie viele Objekte zwischen zwei Zeigern liegen, kann man einfach die Differenz bilden: n = ptr2 - ptr1; // Anzahl Objekte zwischen zwei Zeigern ptr2 ptr1 feld Feldelemente werden mit aufsteigender Adresse gespeichert. Demzufolge muss ptr1 von ptr2 subtrahiert werden Multiplikation und Division von Adressen ist nicht erlaubt Vergleichsoperatoren <, <=, >=, >, == und!= können verwendet werden Beispielsweise liefert ptr2 > ptr1 den Wert 1 und somit wahr.

Zeiger (14) Felder von Zeigern Gutes Mittel bei Feldern unterschiedlicher Länge Mehrdimensionale Felder: alle Teilfelder müssen gleiche Länge haben Häufige Anwendung: Feld von Zeigern auf Zeichenketten p p[0] p[1] p[2] a1 a2 a3 long a1[6]; long a2[3]; long a3[5]; long *p[3]; Initialisierung kann entweder durch Zuweisung oder gleich bei der Definition des Feldes erfolgen p[0] = &a1[0]; p[1] = &a2[0]; p[2] = &a3[0]; long *p[3] = {&a1[0], &a2[0], &a3[0]};

Zeiger (15) Felder von Zeigern Will man auf das 3. Element mit Index 2 des ersten Teil-Feldes zugreifen, so geht folgendes a1[2] p[0][2] Der letzte Ausdruck ist (trotz Anschein) kein zweidimensionales Feld Man müsste, um das erkennbar zu machen, eigentlich folgendes schreiben: *(p[0] + 2) Zu jedem Teil-Feld muss man noch die Länge verwalten, was mit einem zweiten Feld möglich ist Ausnahme: Zeichenketten. Diese sind null-terminiert.

Zeiger (16) Felder von Zeigern Effizientes Sortieren lässt sich realisieren, indem man nur Zeiger auf Felder bzw. Zeichenketten austauscht. p p[0] a1 p[1] p[2] a2 a3 Nach dem Vergleich reicht es aus, die Zeiger auszutauschen long *ptr1; // Zeiger long *ptr2; long a1[6]; // Felder long a2[3]; //... ptr1 = &a1[0]; // Init ptr2 = &a2[0]; //... SwapZeiger(&ptr1, &ptr2); // Parameter sind Adressen der Zeiger, // also Zeiger auf Zeiger void SwapZeiger(long **p1, long **p2) { long *h; // Dreieckstausch h = *p1; *p1 = *p2; *p2 = h; } // end SwapZeiger

Zeiger (17) Zeiger auf Zeiger Beispiel von letzter Folie benutzt einen Zeiger auf einen Zeiger als Parameter, damit der Original-Zeiger für den Tausch manipuliert werden kann Dreieckstausch ist der gleich geblieben, wie bereits im Abschnitt Felder gezeigt Da Zeiger getauscht werden sollen, muss man auf diese zeigen Folgendes nicht empfohlene Beispiel veranschaulicht höhere Zeiger : long feld[6]; // Feld mit 6 Elementen long *ptr1 = &feld[0]; // Zeiger auf das Feld long **ptr2 = &ptr1; // Zeiger auf ptr1 long ***ptr3 = &ptr2; // Zeiger auf ptr2 ptr3 ptr2 ptr1 feld

Zeiger (18) Konstante Zeiger Selbstbeschränkung ist wichtig, um nicht versehentlich unveränderbare Daten zu überschreiben, wie beispielsweise hier möglich: char *ptr; Ein wichtiges Mittel ist, Speicher, auf den der Zeiger zeigt, als konstant zu definieren: const char *ptr; ptr zeigt auf ein Objekt vom Typ char, das konstant ist Falls der Zeiger selbst nicht modifiziert werden darf, sieht das so aus: char * const ptr = &feld[0]; Da der Zeiger nicht modifiziert werden darf, muss er gleich mitinitialisiert werden Soll sowohl der Zeiger als auch das gezeigte Element konstant sein, muss das Schlüsselwort const an beiden Stellen stehen const char * const ptr = &feld[0];