9 Zeiger (Pointer). Dynamischer Speicher



Ähnliche Dokumente
Arrays in C. 1 Grundlagen

10 Die Programmiersprache C99: Zusammenfassung

Zeichenketten (Strings) in C

27 Zufallsvariablen. Erwartungswert. Median. Perzentilen

17 Grundrechenarten für komplexe Zahlen

1 Äquivalenzumformungen, Lösungsmenge

29 Schätzung von Erwartungswert und Varianz

22 Fehlerfortpflanzung und Extrema bei Funktionen mehrerer Veränderlicher

13 Rationale Funktionen

9 Lineare Differentialgleichungen erster und zweiter Ordnung mit konstanten Koeffizienten

9 Eigenschaften von Funktionen. Lineare Funktionen, Potenzen und Wurzeln

22 Lineare Näherung. Anwendungen

7 Abbildungen, Funktionen

27 Zufallsvariablen. Erwartungswert. Median. Perzentilen

Die Programmiersprache C99: Zusammenfassung

19 Folgen. Grenzwerte. Stetigkeit

20 Ableitung. 1 Ableitung

3 Klassen, Attribute, Methoden

Eigenschaften von Funktionen. Lineare Funktionen, Potenzen und Wurzeln

14 Partialbruchzerlegung

In den USA verwendet man statt dessen eckige Klammern, was sich in der Software niederschlägt (mit Ausnahmen wie Wolfram Alpha):

1 Begriff Kombinatorik; Zahl aller Teilmengen

3 Klassen, Attribute, Methoden

7 Dateien und Datenströme (Streams)

8 Design Patterns. Events

3 Mengen, Logik. 1 Naive Mengenlehre

23 Integral. 1 Idee des Integrals

16 Fourier-Reihe mit komplexer Exponentialfunktion

2 Geradengleichungen in Parameterform. Länge und Skalarprodukt

15 Restabschätzung nach Taylor. Potenzreihen

In den USA verwendet man statt dessen eckige Klammern, was sich in der Software niederschlägt (mit Ausnahmen wie Wolfram Alpha):

25 Elementare Längen, Flächen und Volumina. Bogenlänge. Rotationskörper

2 Grundlagen zu Ableitung und Integral

8 Relationen, Umkehrung

Die nummerierten Felder bitte mithilfe der Videos ausfüllen:

4 Vererbung, Polymorphie

11 Polynome. 1 Begriffe, Verlauf. Ein Ausdruck der Art

14 Schmiegeparabel und Freunde, Taylor-Reihe

4 Zahlenbereiche. 1 Natürliche, ganze und rationale Zahlen

Informatik 2 für Regenerative Energien

24 Mehrdimensionale Integrale

6 Vektoranalysis Kurven

16 Trigonometrie: Sinus und Freunde, Arcusfunktionen

Potenzen und Wurzeln komplexer Zahlen. Eulersche Identität. Polardarstellung. Additionstheoreme. Vollständige Faktorisierung von Polynomen

18 Kontinuierliche Fourier-Transformation. Laplace-Transformation

Für ist Element von und ist nicht Element von schreibt man: 2

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

9 Fourier-Transformation

Dynamischer Speicher

Die nummerierten Felder bitte mithilfe der Videos ausfüllen:

Informatik 2 für Regenerative Energien

1 Wahrscheinlichkeitsrechnung und Zufallsvariablen

Informatik 2 für Regenerative Energien

Exponentialfunktionen, Eulersche Zahl, Logarithmen

2 Verteilungen. Zoltán Zomotor. Versionsstand: 1. April 2015, 10:29. Die nummerierten Felder bitte während der Vorlesung ausfüllen. Inhaltsverzeichnis

8 Dynamische Systeme. 1 Begriff und Anwendung

C/C++-Programmierung

13 Automaten und formale Sprachen

Programmieren I. Kapitel 12. Referenzen

Informatik 2 für Regenerative Energien

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

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

9 Multithreading. 1 Idee des Multithreading

6. Zeiger Allgemeines Definition eines Zeigers

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

IP Rechnen. Modul 127. Copyright by Janik von Rotz

Software Entwicklung 1

Schleifen und Arrays Javakurs

Programmierung mit C Zeiger

Transkript:

9 Zeiger (Pointer). Dynamischer Speicher Jörn Loviscach Versionsstand: 25. September 2013, 18:07 Die nummerierten Felder sind absichtlich leer, zum Ausfüllen beim Ansehen der Videos: http://www.j3l7h.de/videos.html This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/de/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. Bitte hier notieren, was beim Bearbeiten unklar geblieben ist 1 Idee Jede Variable muss irgendwo im Speicher abgelegt sein. (Oder in einem Register, aber diese Komplikation ignorieren wir mal.) Der Speicher ist in Bytes unterteilt; man kann zählen, bei dem wievielten Byte des Speichers die Daten einer bestimmten Variable beginnen: Das ist die Adresse der Variable: 1 In C und C++ kann man mit dem Operator & nach der Adresse einer Variablen fragen und diesen in einer Zeigervariablen ablegen. Deren Typ ist dann Zeiger auf int usw., angezeigt durch ein Sternchen: 1

2 ZEIGERARITHMETIK 2 2 Demo mit der Speicheransicht im Debugger. Das Sternchen * ist auch ein Operator, um einen Zeiger zu einer Variablen zu machen, die man lesen und schreiben kann: 3 Das ist natürlich wieder riskant, weil man so irgendwo im Speicher lesen und schreiben kann: 4 Die Adresse 0 hat eine besondere Bedeutung: Kein gespeichertes Objekt darf hier liegen. Mit dem Wert 0 gerne mit dem Makro NULL aus <stddef.h> geschrieben kann man also kennzeichnen, dass ein Zeiger ungültig ist. Auf größeren Rechnern als dem Mikrocontroller führt jeder Zugriff darauf [dereferencing a null pointer] zum Abbruch des Programms führen. In moderneren Sprachen muss man dafür immer ausdrücklich null schreiben, niemals 0. Also lieber auch in C und C++ immer NULL schreiben. 2 Zeigerarithmetik Der Name eines Arrays steht in C und C++ für einen Zeiger auf das erste Element: 5 Das geht auch umgekehrt: Ein Zeiger kann wie ein Array verwendet werden. Beispiel:

3 DYNAMISCHER SPEICHER 3 6 Obendrein kann man auch direkt mit Zeigern rechnen ( Zeigerarithmetik ): Zu einem Zeiger etwas zu addieren, heißt, ihn um genau so viele Speicherstellen des entsprechenden Typs weiterzustellen also im Zweifelsfall nicht um diese Zahl an Bytes: 7 Nach int a[] = {1, 2, 3}; int *p = a; gibt es damit mindestens vier Möglichkeiten, auf a[2] zuzugreifen: 8 Das Suchen aller 'a' und Ersetzen durch 'e' in einer Zeichenkette kann man nun so schreiben: 9 3 Dynamischer Speicher Anders als in C99 und in modereren Sprachen muss man für Arrays in C++ und alten Varianten von C im Programmtext eine feste Größe angeben. Dort darf man zum Beispiel nicht dies schreiben: 10 In der IAR Embedded Workbench ist auch in C99 noch der Schalter Allow VLA in Options > C/C++ Compiler > Language nötig.

3 DYNAMISCHER SPEICHER 4 Dass man sich schon vor dem Compilieren auf eine Größe der Arrays festlegen muss, ist natürlich äußerst ungeschickt. Oft weiß man vorher nicht, wie viele Daten man unterbringen muss, und hat aber auch nicht genug Speicher, um einfach auf Verdacht so viel wie nur möglich zu reservieren. Um trotzdem mit veränderlichen Mengen an Daten umzugehen, kann man C mit der int <stdlib.h> deklarierten Funktion malloc bitten, einem einen Zeiger auf soundsoviele freie Bytes im Speicher zu geben. Wenn man diese Bytes nicht mehr benötigt, muss man sie mit free wieder freigeben, sonst bleiben sie bis zum Programmende blockiert ( Speicherleck ). So sieht das aus: 11 Der Programmierer ist dafür verantwortlich, dass free aufgerufen wird und zwar nur einmal für denselben Zeiger. Es ist eine gute Praxis, einen Zeiger nach dem Freigeben auf NULL zu setzen. Dann führt jeder Zugriff darauf zum Absturz statt zu korrupten Daten. Außerdem garantiert der Standard, dass free(null) nichts tut. Bei den üblichen automatisch Variablen sorgt der Compiler selbst dafür, dass ihr Speicher wieder freigegeben wird. Beispiel: 12 malloc liefert einen Nullzeiger, wenn kein Platz mehr zu haben ist (Demo). Also sollte prüfen, ob das Ergebnis null ist und in diesem Fall zum Beispiel keine neuen Messwerte mehr annehmen o. ä. Auf dem MSP430G2231 gibt es mit 128 Byte derart wenig Platz, dass malloc sowieso immer fehlschlägt. malloc gibt den Speicher im Zweifelsfall mit den Werten gefüllt, die vorher mal drinstanden. Die Funktion calloc setzt dagegen alle Bits auf null. Mit realloc kann man bereits reservierten Speicher vergrößern oder verkleinern. Mehrdimensionale Arrays, deren Größe beim Compilieren noch nicht feststeht, kann man damit über einen Umweg bauen:

3 DYNAMISCHER SPEICHER 5 13 Demo in der Speicheransicht des Debuggers. Für den leichteren Umgang mit Zeigern auf Strukturen kann man statt (*p).m übersichtlicher p->m schreiben: 14