====== Zeiger (Pointer) ======
Zeiger (engl. pointers) sind Variablen, die als Wert die Speicheradresse einer anderen Variable enthalten.
Jede Variable wird in C++ an einer bestimmten Position im Hauptspeicher abgelegt. Diese Position nennt man Speicheradresse (engl. memory address). C++ bietet die Möglichkeit, die Adresse jeder Variable zu ermitteln. Solange eine Variable gültig ist, bleibt sie an ein und derselben Stelle im Speicher.
Am einfachsten vergegenwärtigt man sich dieses Konzept anhand der globalen Variablen. Diese werden außerhalb aller Funktionen und Klassen deklariert und sind überall gültig. Auf sie kann man von jeder Klasse und jeder Funktion aus zugreifen. Über globale Variablen ist bereits zur Kompilierzeit bekannt, wo sie sich innerhalb des Speichers befinden (also kennt das Programm ihre Adresse).
Zeiger sind nichts anderes als normale Variablen. Sie werden deklariert (und definiert), besitzen einen Gültigkeitsbereich, eine Adresse und einen Wert. Dieser Wert, der Inhalt der Zeigervariable, ist aber nicht wie in unseren bisherigen Beispielen eine Zahl, sondern die Adresse einer anderen Variable oder eines Speicherbereichs. Bei der Deklaration einer Zeigervariable wird der Typ der Variable festgelegt, auf den sie verweisen soll.
===== Zeiger vermeiden =====
Eines vorweg: Die direkte Verwendung von Zeigern ist gefährlich und kann selbst bei erfahrenen Programmierern gelegentlich zu Fehlern führen. Alleine schon aus diesem Grund solltest du Pointer nur verwenden, wenn es nicht anders geht. Bei Standarddatentypen (Integer, Boolean, Double, …) wirst du in der Regel keine Zeiger brauchen.
===== Notwendigkeit von Zeiger =====
Zeiger sind nötig um dynamisch allokierten Speicher zu nutzen. Der new-Operator gibt einen entsprechend typisierten Pointer zurück, der auf den neu angelegten Speicherbereich zeigt. Somit sind Zeiger für eine saubere objektorientierte Programmierung unabdingbar. Das ist allerdings ein Kapitel, das für Anfäger doch noch eher ungeeignet ist und anfangs getrost beiseite geschoben werden kann.
===== Beispiele =====
#include
int main() {
int Wert; // eine int-Variable
int *pWert; // eine Zeigervariable, zeigt auf einen int
int *pZahl; // ein weiterer "Zeiger auf int"
Wert = 10; // Zuweisung eines Wertes an eine int-Variable
pWert = &Wert; // Adressoperator '&' liefert die Adresse einer Variable
pZahl = pWert; // pZahl und pWert zeigen jetzt auf dieselbe Variable
===Beispielhafte Speicherbelegung des Programms im Hauptspeicher:===
^Variable^Adresse^Wert|
|Wert|0x0001|10|
|*pWert|0x0005|0x0001|
|*pZahl|0x0009|0x0001|
|…|.|.|
|…|.|.|
Der Adressoperator & kann auf jede Variable angewandt werden und liefert deren Adresse, die man einer (dem Variablentyp entsprechenden) Zeigervariablen zuweisen kann. Wie im Beispiel gezeigt, können Zeiger gleichen Typs einander zugewiesen werden. Zeiger verschiedenen Typs bedürfen einer Typumwandlung. Die Zeigervariablen pWert und pZahl sind an verschiedenen Stellen im Speicher abgelegt, nur die Inhalte sind gleich.
Wollen Sie auf den Wert zugreifen, der sich hinter der im Zeiger gespeicherten Adresse verbirgt, so verwenden Sie den Dereferenzierungsoperator *.
*pWert += 5;
*pZahl += 8;
std::cout << "Wert = " << Wert << std::endl;
===Beispielhafte Speicherbelegung des Programms im Hauptspeicher:===
^Variable^Adresse^Wert|
|Wert|0x0001|10 --> 15 --> 23|
|*pWert|0x0005|0x0001|
|*pZahl|0x0009|0x0001|
|…|.|.|
|…|.|.|
===Ausgabe:===
Wert = 23
Man nennt das den Zeiger dereferenzieren. Im Beispiel erhalten Sie die Ausgabe Wert = 23, denn pWert und pZahl verweisen ja beide auf die Variable Wert.
Um es noch einmal hervorzuheben: Zeiger auf Integer (int) sind selbst keine Integer. Den Versuch, einer Zeigervariablen eine Zahl zuzuweisen, beantwortet der Compiler mit einer Fehlermeldung oder mindestens einer Warnung. Hier gibt es nur eine Ausnahme: die Zahl 0 darf jedem beliebigen Zeiger zugewiesen werden. Ein solcher Nullzeiger zeigt nirgendwohin. Der Versuch, ihn zu dereferenzieren, führt zu einem Laufzeitfehler.
==== Ein weiteres Beispiel.... ====
int zahl = 7;
int *zeiger;
zeiger = &zahl;
printf("Zeiger-Wert: %d\n", *zeiger);
Ein **Zeiger repräsentiert eine Adresse** und nicht wie eine Variable einen Wert. Will man auf den Wert der Adresse zugreifen, auf die ein Zeiger zeigt, muss der Stern * vor den Namen gesetzt werden.
{{:inf:inf8bi_201819:3:pasted:20190121-155046.png}}
===== Zeiger auf Zeiger =====
Zeiger zeigen auf Adressen. Sie können nicht nur auf die Adressen von Variablen, sondern auch auf die Adressen von Zeigern verweisen. Dies erreicht man mit dem doppelten Stern-Operator * * .
int zahl=7;
int *zeiger = &zahl;
int **zeigerAufZeiger = &zeiger;
cout << "Wert von zeigerAufZeiger -> zeiger -> zahl:" << **zeigerAufZeiger;
=== Ausgabe ===
Wert von zeigerAufZeiger -> zeiger -> zahl: 7