Propädeutikum 2015
Vorbereitungskurs Informatikstudium Erfolgreich Studieren Programmieren (C-Kurs) guettler@informatik.uni-leipzig.de Universität Leipzig Institut für Informatik Technische Informatik 2
Überblick Kapitel 18 Zeitmanagement und Persönlichkeit Kapitel 19 Zeiger (Pointer) 3
Kapitel 18 Zeitmanagement und Persönlichkeit 4
Kapitel 18 Zeitmanagement und Persönlichkeit Zeitmanagement und Persönlichkeit Wie nutze ich meine Zeit? 5
Zeitplanung - Kernfragen Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich? Prioritäten setzen Entscheidung, welche Aufgaben nicht erledigt werden Was tue ich wann? Konkrete Zeitplanung Was tue ich wie? Mit Arbeitsweisen Zeit sparen Motivation Was Du heute kannst besorgen 6
Was tue ich? Der Stellenwert des Studiums Kapitel 18 Zeitmanagement und Persönlichkeit Was will ich mit meinem Leben anfangen? Warum eigentlich studieren? Was genau damit erreichen? Notwendig für bestimmten Beruf? Interesse am Thema? Nichts besseres eingefallen? Erwartung der Eltern? Sich vor jemandem profilieren? Grundlage für Motivation, wie ich studiere! 7
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich? Prioritäten setzen Was ist mir wichtig? Familie Studium Freunde Hobbies Sport Job 8
nicht wichtig wichtig Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich? Prioritäten setzen im Alltag Wichtig oder dringend? Typische Aufschiebeaufgaben Oberste Priorität nicht dringend dringend unterbewusste Aufgaben Typische vorgeschobene Aufgaben 9
nicht wichtig wichtig Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich? Prioritäten setzen im Alltag Wichtig oder dringend? Typische Aufschiebeaufgaben Oberste Priorität nicht dringend dringend unterbewusste Aufgaben Typische vorgeschobene Aufgaben 10
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung Generelles Zeitplanungssystem muss für mich passen Pufferzeiten für Unerwartetes Eigenen Rhythmus der verplanten Zeit beachten Physiologische Leistungskurve Phasen im Semester Persönliche Ereignisse 11
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung Kanban-Tafel Was muss ich noch tun? Woran arbeite ich gerade? Was habe ich schon geschafft? Übungen Linare Algebra Lernplan DBs 1 aufstellen Übungen Technische Informatik 2 Hardware- Praktikum vorbereiten mit Sven zum AGRA- Flohmarkt Vorlesung MuP 2 nachbereiten Themenübersicht AuD 1+2 Klettern mit Sara und Tim Ein ganz neues Leben lesen Kino mit Jens: StarWars 12
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung - Mindmaps 13
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung Tagesplanung (am Vorabend) Markierung auf Mindmap oder Kanban-Tafel Prioritäten setzen Wochenplanung Stundenplan mit fixen Terminen als Basis Kiesel -Prinzip: von groß nach klein Pufferzeit nicht vergessen 14
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung - Wochenplanung 15
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung - Wochenplanung 16
Kapitel 18 Zeitmanagement und Persönlichkeit Was tue ich wann? Zeitplanung - Wochenplanung 17
Kapitel 19 Zeiger (Pointer) 18
Zeiger Definition engl. pointer Datentyp der Adressen von Speicherplätzen verwaltet Zeiger selbst ist ganz normale Variable, der Zahl (Speicheradresse) hält Ermöglicht Manipulation von Inhalten über Speicheradressen Pointer belegt nur so viel Platz, dass er eine Adresse speichern kann 32-Bit Betriebssystem = 4 Byte 64-Bit Betriebssystem = 8 Byte Neben int und float drittes Grundobjekt von C Nützlich um Speicherkopien zu vermeiden (Strukturen, etc.) 19
Zeiger Überblick 1. Zeiger int * i; 2. Zeiger auf Zeiger int ** k = &i; 3. Zeigerarithmetik int * j = i + 3; 4. Zeiger und Felder i+1 entspricht i[1]; 5. Dynamischer Speicher malloc(), free() 20
Zeiger Typische Verwendung 1. Nutzung u. Änderung von Variableninhalten in Unterfunktionen (Call-by-Reference) Veränderung sonst nicht anders möglich, denn Parameter werden bei C-Funktionsaufruf nur kopiert (Call-By-Value) 2. Dynamische Speicherallokation Bereitstellung von Speicherplatz zur Laufzeit Gegensatz zur statischen Speicherallokation zur Compilezeit 21
Einfache Zeiger Beispiel int main(void) { int i = 5; // int-variable, mit 5 initialisiert. int * ptr_i; // Zeiger auf eine int-variable, nicht // initialisiert. Solche Zeiger dürfen // nicht verwendet werden, sie zeigen auf // auf einen zufälligen Speicherbereich! int* ptr_j; // Das gleiche wie oben. int *ptr_k; // Das gleiche wie oben. int * ptr_l, ptr_m; // Achtung: ptr_m ist jetzt kein Zeiger! int * ptr_n, *ptr_o; // ptr_o ist jetzt auch ein Zeiger. } ptr_i = &i; // Mit dem Adressoperator & holen wir uns die // Speicheradresse von i und speichern sie im // Zeiger ptr_i. return 0; 22
Einfache Zeiger Beispiel #include <stdlib.h> int main(void) { int * ptr_i = NULL; // Zeiger auf eine int-variable, mit NULL // initialisiert. Solche Zeiger dürfen // nicht verwendet werden, sie zeigen auf // auf einen ungültigen Speicherbereich! // Zeigern die nicht verwendet werden, sollte // immer NULL oder 0 zugewiesen werden. So lässt // sich prüfen, ob sie auf einen gültigen // Speicherbereich verweisen. int * ptr_j = 0; // Auch ok. int const * ptr_k; // Zeiger auf eine konstante int-variable. int * const ptr_l; // Konstanter Zeiger auf eine int-variable. int const * const ptr_m;// Konstanter Zeiger auf eine konstante int- // Variable. return 0; } 23
Einfache Zeiger Syntax Datentyp * Variablenname; Semantik Pointer zeigt auf Speicherplatz vom angegebene Datentyp char, int, struct... Pointertyp bestimmt also Interpretation beim Zugriff auf Speicherplatz Pointer verhält sich wie normale Variable z.b. lokal (nur in einem Block) oder auch global gültig Hinweise Speicherplatz auf den Pointer zeigt, kann irgendwo sein Speicherplatz kann unterschiedliche Lebensdauer haben 24
Einfache Zeiger Beispiel int main(void) { int i = 5; // int-variable, mit 5 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i return 0; } i ptr_i Speicher??... 5... 35... sizeof(int) sizeof(int) sizeof(int *) Adresse 0 1 35 80 & heißt Adress-/Referenzierungsoperator 25
Einfache Zeiger Beispiel int main(void) { int i = 5; // int-variable, mit 5 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i *ptr_i = 6; // Speichere indirekt (über Zeiger) 6 in i. return 0; } i ptr_i Speicher??... 6... 35... sizeof(int) sizeof(int) sizeof(int *) Adresse 0 1 35 80 & heißt Adress-/Referenzierungsoperator * heißt Dereferenzierungsoperator 26
Einfache Zeiger Beispiel int main(void) { int i = 5, j = 7; // int-variablen, mit 5 und 7 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i *ptr_i = j; // Speichere indirekt (über Zeiger) j in i. return 0; } j i ptr_i Speicher? 7... 7... 35... sizeof(int) sizeof(int) sizeof(int *) Adresse 0 1 35 80 & heißt Adress-/Referenzierungsoperator * heißt Dereferenzierungsoperator 27
Einfache Zeiger Beispiel int main(void) { int i = 5, j = 7; // int-variablen, mit 5 und 7 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i j = *ptr_i; // Speichere indirekt (über Zeiger) i in j. return 0; } j i ptr_i Speicher? 5... 5... 35... sizeof(int) sizeof(int) sizeof(int *) Adresse 0 1 35 80 & heißt Adress-/Referenzierungsoperator * heißt Dereferenzierungsoperator 28
Einfache Zeiger Beispiel int main(void) { int i = 5, j = 7; // int-variablen, mit 5 und 7 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i j = *ptr_i; // Speichere indirekt (über Zeiger) i in j. ptr_i = &j; // Weise ptr_i die Adresse von j zu. return 0; } Speicher j? 5... 5... i ptr_i 1... sizeof(int) sizeof(int) sizeof(int *) Adresse 0 1 35 80 & heißt Adress-/Referenzierungsoperator * heißt Dereferenzierungsoperator 29
call-by-value Beispiel Ausgabe: 0 0 // call-by-value #include <stdio.h> void function(int i); int { main(void) int i = 0; // int-variable i, mit 0 initialisiert printf( %d, i); // Wert von i ausgeben function(i); // i an function übergeben printf( %d, i); // Wert von i ausgeben function hat i nicht verändert, da sie lediglich mit einer Kopie arbeitet. } return 0; void function(int i) { i = 1; } 30
call-by-value Beispiel int main(void) { int i = 0; } return 0; Speicher???...?... Adresse 0 1 2 80 31
call-by-value Beispiel int main(void) { int i = 0; printf( %d, i); } return 0; Speicher???... 0... Adresse 0 1 2 80 32
call-by-value Beispiel int main(void) { int i = 0; printf( %d, i); function(i); } return 0; Speicher Kopie?? 0... 0... Adresse 0 1 2 80 33
call-by-value Beispiel int main(void) { int i = 0; printf( %d, i); function(i); } return 0; Speicher Kopie?? 1... 0... Adresse 0 1 2 80 34
call-by-value Beispiel int main(void) { int i = 0; printf( %d, i); function(i); printf( %d, i); return 0; } Speicher Kopie?? 1... 0... Adresse 0 1 2 80 35
call-by-reference Beispiel Ausgabe: 0 1 // call-by-reference #include <stdio.h> void function(int * i); function hat i verändert, da sie mit dem Original arbeitet. int { main(void) int i = 0; // int-variable i, mit 0 initialisiert printf( %d, i); // Wert von i ausgeben function(&i); // Adresse von i an function übergeben printf( %d, i); // Wert von i ausgeben } return 0; void function(int * i) { *i = 1; // i dereferenzieren und neuen Wert speichern } 36
call-by-reference Beispiel int main(void) { int i = 0; } return 0; Speicher???...?... Adresse 0 1 2 80 37
call-by-reference Beispiel int main(void) { int i = 0; printf( %d, i); } return 0; Speicher???... 0... Adresse 0 1 2 80 38
call-by-reference Beispiel int main(void) { int i = 0; printf( %d, i); function(&i); } return 0; Speicher???... 0... Adresse 0 1 2 80 39
call-by-reference Beispiel int main(void) { int i = 0; printf( %d, i); function(&i); } return 0; Speicher???... 1... Adresse 0 1 2 80 40
call-by-reference Beispiel int main(void) { int i = 0; printf( %d, i); function(&i); printf( %d, i); return 0; } Speicher???... 1... Adresse 0 1 2 80 41
Zeiger auf Zeiger Syntax Datentyp ** Variablenname; Semantik Zeiger verweist auf Speicherplatz eines Zeigers vom angegebene Datentyp Manipulation von referenzierten Zeigern möglich Theoretisch keine Grenze: *, **, ***,... 42
Zeiger auf Zeiger Beispiel int main(void) { int i = 5; // int-variable, mit 5 initialisiert. int * ptr_i = &i; // Zeiger ptr_i hält Adresse von i int ** ptr_ptr_i = &ptr_i; // Zeiger ptr_ptr_i hält Adresse von ptr_i return 0; } i ptr_i ptr_ptr_i Speicher?? 5... 2... 80 sizeof(int) sizeof(int *) sizeof(int **) Adresse 0 1 2 80 120 Hinweis: sizeof(int *) == sizeof(int **) Pointer haben immer dieselbe Größe 43
Zeiger auf Zeiger Beispiel int main(void) { int i = 5; // int-variable, mit 5 initialisiert. int * ptr_i = &i; // Zeiger auf eine int-variable, mit der // Adresse von i initialisiert. int ** ptr_ptr_i = &ptr_i; // Zeiger auf Zeiger auf eine int-variable // mit der Adresse von ptr_i initialisiert. i = 7; // Weise i den Wert 7 zu. *ptr_i = 7; // Weise i den Wert 7 zu. **ptr_ptr_i = 7; // Weise i den Wert 7 zu. } return 0; 44
Zeigerarithmetik Zeigerarithmetik auch: Pointerarithmetik, Adressarithmetik Addition (Subtraktion) von int-werten zu der im Zeiger gespeicherten Adressen Wichtigstes Sprachmittel im Umgang mit dynamischen Speicher Fehleranfällig Prüfung der Grenzen unterliegt Programmierer Verzicht von Pointern in vielen Programmiersprachen (Java, Pascal) 45
Zeigerarithmetik Syntax Zeigervariable++; Zeigervariable--; Zeigervariable = Zeigervariable + int_wert; Zeigervariable = Zeigervariable - int_wert; Zeigervariable += int_wert; Zeigervariable -= int_wert; Semantik Erhöhung (bzw. Verringerung) der Adresse um n-byte * int_wert n-byte ist Größe des Grunddatentyps (char, int, struct...) Größenermittlung mit sizeof(grunddatentyp) 46
Zeigerarithmetik Beispiel int main(void) { char i = 0; char * ptr_i = &i; ptr_i++; ptr_i -= 2; return 0; } -2*sizeof(char) +1*sizeof(char) Speicher?? 0?... Adresse 0 1 2 3 47
Zeiger und Felder Feldnamen Sind auch nur Zeiger, jedoch konstant Zeigen immer auf erstes Elemen des Feldes Bei int liste[10] ist liste vom Typ int * const Äquivalenzen [] wird Indexoperator genannt Felder werden intern in Zeiger umgewandelt v[0] entspricht *v v[i] entspricht *(v + i) &v[0] entspricht v &v[i] entspricht v + i 48
Dynamischer Speicher Dynamischer Speicher Von C-Bibliothek bereitgestellter Speicher zur Laufzeit Allokieren: malloc(), calloc(), realloc() Freigeben: free() Typischer Einsatz von Zeigern Probleme Speicherlecks, falls Zeiger geändert wird Speicherlecks, falls keine Freigabe nach Benutzung Fehlverweise, falls Zeiger auf ungültigen Speicherbereich verweist 49
Dynamischer Speicher Beispiel // speicher.c #include <stdio.h> #include <stdlib.h> int main(void) { // Fordere Speicher zur Laufzeit an. int * ptr = (int *) malloc(10 * sizeof(int)); // Prüfe den Erfolg unserer Speicheranforderung. if (ptr == NULL) puts( Konnte keinen Speicher reservieren! ); else { } puts( Erfolgreich free(ptr); Speicher reserviert! ); } return 0; 50
Noch nicht genug? Funktionsnamen Sind auch nur Zeiger, jedoch konstant Zeigen immer auf erstes Elemen des Feldes Bei void func(void) ist func vom Typ void (*)(void) Exotische Beispiele Zeiger auf Funktion, die nichts zurückgibt und int übernimmt void (* ptr_func)(int) ptr_func ist jetzt die Zeigervariable Zeiger auf erstes Element eines int-array der Größe [10][5] int (* ptr_array)[5] ptr_array ist jetzt die Zeigervariable Array mit 10 Funktionszeigern, die nichts zurückliefern und einen int-zeiger übernehmen void (* ptr_func_array[10])(int *) ptr_func_array ist jetzt der Arrayname 51
Die Vorlesungen am Freitag (Info, Mathe) finden im Augustusplatz, Paulinum Felix-Klein-Hörsaal (5. Etage) statt 52
Viel Erfolg! Propädeutikum Bis morgen! 2015