Übung zur Vorlesung Programmieren in C 6 Pointers Marvin Gülker Ruhruniversität Bochum Wintersemester 2015/2016 Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 1 / 29
Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 2 / 29
Lösung vom letzten Mal Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 3 / 29
Lösung vom letzten Mal Kernpunkte Sie können mit Mehrdateiprojekten umgehen. Sie haben verstanden, wozu der Linker gut ist. Erstellung von Funktionen. Argumente und Parameter in Funktionen, Call-by-Value. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 4 / 29
Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 5 / 29
Der Arbeitsspeicher Runner1616/wikimedia.org CC-BY-SA 3.0 Unported Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 6 / 29
Speicherort von Variablen 0 0 1 0 1 0 1 1 1 int meinevariable; Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 7 / 29
Zeigersemantik (Kurzanriss) &meinevariable; 0 0 1 0 1 0 1 1 1 int meinevariable; Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 8 / 29
Syntax int x = 42; int* p_int = &x; Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 9 / 29
Vorsicht int* p_a, b; /* p_a ist ein int*, b ist bloß ein int */ /* Daher besser: */ int* p_a; int* p_b; /* Oder */ int *p_a, *p_b; Welche Vorgehensweise Sie wählen, ist Geschmackssache. Bleiben Sie aber konsistent. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 10 / 29
Übung I int x = 42; int* p_x = &x; *p_x = 50; /* Dereferenzierung */ printf("x hat den Wert %d\n", x); /* =>? */ printf("*p_x hat den Wert %d\n", *p_x); /* =>? */ printf("p_x hat den Wert %d\n", p_x); /* =>? */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 11 / 29
Nutzer der Flagge -Wall profitieren. foo.c:8:10: Warnung: Format»%d«erwartet Argumenttyp»int«, aber Argument 2 hat Typ»int *«[-Wformat=] Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 12 / 29
Übung II int x = 42; int *p_x = &x; int y = 50; *p_x = y; printf("x: %d\n", x); /* =>? */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 13 / 29
Übung III int x = 42; int y = 50; int* p_x = &x; int* p_x2 = &x; int** pp_x = &p_x; p_x = &y; x = 10; *p_x2 = 15; **pp_x = 100; printf("x: %d\ny: %d\n", x, y); /*?? */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 14 / 29
Nullpointer Einen Pointer, der auf gar nichts zeigen soll, initialisiert man mit NULL. NULL ist ein Makro, das die Standardbibliothek als 0 definiert. Empfehlung: Zunächst ungenutzte Pointer immer auf NULL initialisieren. Ein Pointer auf 0x0 springt beim Debugging sofort ins Auge! #include <stdib.h> /*... */ int *ptr = NULL; int *ptr = 0; /* Gleichwertig, aber ungebräuchlich */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 15 / 29
Benennung Zeiger sind ganz normale Variablen. Um im Code sofort zu sehen, dass eine Variable ein Pointer ist, empfehle ich, solche Variablen mit p_ zu beginnen. Das ist eine gekürzte Variante der sog. ungarischen Notation. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 16 / 29
Call-by-Reference C kennt kein Call by Reference. Aber Pointer werden wie jeder andere Wert auch selbst by value übergeben. Ergebnis: Die Adresse wird kopiert. Durch Dereferenzierung kommt man dann an die Speicherstelle heran, auf die auch die äußere Variable zugreift. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 17 / 29
Beispiel & Übung #include <stdio.h> void func(double* p_val) { double x = 5.0; *p_val = x * 3; } int main() { double x = 42.0; double y = 42.0; func(&x); /* Man beachte den Adressoperator! */ /* Dasselbe mit y */ double* ptr = &y; func(ptr); /* kein &; ist ja schon ein Zeiger */ } printf("x: %f\ny: %f\n", x, y); /*?? */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 18 / 29
const Will man Dereferenzierung erlauben, aber Wertveränderungen verbieten, benutzt man einen const-pointer (Mares: Zeiger auf Konstante ). Das ist praxisrelevant. Ansonsten sind Zeiger halt auch nur Variablen. Genauso wie normale Variable kann man eine Änderung ihres Werts (nicht: des dereferenzierten Werts) verbietet. Dann hat man einen konstanten Zeiger. Das ist verhältnismäßig selten. Man kann auch beides mischen, also einen konstanten Zeiger auf eine Konstante. Kommt faktisch nicht vor. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 19 / 29
Realworld-Beispiel (libxml2) Search and get the value of an attribute associated to a node. [ ] Returns: the attribute value or NULL if not found. [ ] typedef unsigned char xmlchar; struct xmlnode { void * _private; xmlelementtype type; const xmlchar * name; struct xmlnode * children; struct xmlnode * last; /*... */ }; xmlchar * xmlgetprop (const xmlnode * node, const xmlchar * name); Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 20 / 29
Arrays Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 21 / 29
Arrays Allgemein Ein Array ist eine Liste einer bestimmten Anzahl von Werten. Alle Werte haben denselben Typ. Jeder Wert hat einen Index; der Index des ersten Elements ist 0. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 22 / 29
Arrays Beispiel int ary[10]; /* Ein Array mit zehn Werten vom Typ int. */ ary[0] = 15; /* Erstes Element auf 15 setzen */ printf("%d\n", ary[0]); /* => 15 */ /* Letztes Element auf 20 setzen */ int x = 9; ary[x] = 20; printf("%d\n", ary[9]); /* => 20 */ ary[10] = 50; /* FEHLER! Wahrscheinlich: Programmabsturz */ Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 23 / 29
Lösungshinweise Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 24 / 29
Lösungshinweise Lösungshinweise Sie erhalten in Moodle eine fertige main()-funktion und müssen nur die Funktion prim() implementieren. Diese bitte in einer eigenen Datei implementieren (Mehrdateiprojekt gewünscht). Sie werden bei korrekter Erfüllung der Aufgabenstellung Pointer benötigen. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 25 / 29
Für Fortgeschrittene Gliederung 1 Lösung vom letzten Mal 2 Zeiger (Pointers) 3 Arrays 4 Lösungshinweise 5 Für Fortgeschrittene Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 26 / 29
Für Fortgeschrittene Sieb des Eratosthenes Anspruchsvollere Primzahlfindefunktion. Beschreibung in der Wikipedia; in ihrem eigenen Interesse, lesen Sie nicht den Abschnitt Implementierung, sondern versuchen Sie selbst die Implementierung anhand des Abschnitts Funktionsweise herauszufinden. Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 27 / 29
Für Fortgeschrittene Debugging Debugging ist der Prozess der Fehlersuche und -behebung. Ein Debugger kann das Programm anhalten, Variablenwerte ausgeben, den Stacktrace (Kette von geschachtelten Funktionsaufrufen seit main() mit Zeilennummern) ausgeben und vieles mehr. Das ist extrem praxisrelevant. Kein Programmierer ohne Debugger. Der gängigste Debugger für C/C++-Programme ist GDB. Er ist in Code::Blocks enthalten und kann über den roten Pfeil aktiviert werden. Danach können Sie im Textfenster unten Kommandos eingeben. Dokumentation: https: //sourceware.org/gdb/download/onlinedocs/gdb/index.html Wichtigste Kommandos: b p bt up down Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 28 / 29
Für Fortgeschrittene Danke für die Aufmerksamkeit E-Mail marvin.guelker@rub.de Folien http://homepage.rub.de/marvin.guelker/ Diese Präsentation unterliegt der CreativeCommons-Lizenz CC-BY-ND 4.0 (https://creativecommons.org/licenses/by-nd/4.0/deed.de). Marvin Gülker (Ruhruniversität Bochum) 6 Pointers Wintersemester 2015/2016 29 / 29