Ein Zeiger (engl. Pointer) ist ein typisierter Verweis
auf einen Speicherbereich, sozusagen ein Link auf den Speicher. Sehen
wir uns wiederum das Beispiel an, um
hinter die Idee zu kommen.
Ein einfaches Beispiel
Die Funktion einfach
enthält
folgenden Code:
//
Variable im Speicher anlegen
int
a = 42;
// Zeiger auf Integer
anlegen
int* p;
// Wert von a ausgeben
cout << a <<
endl;
// Referenzierung:
// p auf a zeigen lassen
p = &a;
// Dereferenzierung:
// Das, worauf p zeigt,
verändern (also a)
*p = 23;
// Wert von a ausgeben
cout << a <<
endl;
Durch den Befehl p = &a;
lassen wir p auf a
zeigen. a liegt irgendwo in unserem Speicher.
p enthält nach dieser Zuweisung
als Wert die Speicheradresse von a. Durch
das Und (&) vor einer Variablen
können wir also deren Anfangsadresse im Speicher bestimmen und
einem Pointer zuweisen.
Mit *p = 23;
verändern wir anschließend das, worauf p zeigt. An
den Inhalt eines Zeigers kommen wir also über den Stern (*)
vor einem Zeiger wieder heran.
Danach enthält die Variable a den Wert 23.
Zeiger und Felder
Sehen wir uns die zweite Funktion array
an.
//
Array im Speicher anlegen
int
a[2] = { 42, 42 };
// Zeiger auf Integer
anlegen
int* p;
// Werte von a ausgeben
cout << a[0]
<< " | " << a[1]
<< endl;
// Referenzierung:
// p auf a zeigen lassen
p = a;
// Dereferenzierung:
// Das, worauf p zeigt,
verändern (also a[0])
*p = 23;
// Werte von a ausgeben
cout << a[0]
<< " | " << a[1]
<< endl;
// Dereferenzierung mit
Index:
// Nächstes
Element
verändern (also a[1])
p[1] = 216;
// Werte von a ausgeben
cout << a[0]
<< " | " << a[1]
<< endl;
Im Falle von Arrays benötigen wir keinen
&-Operator, da C++ Arrays schon als Speicherbereich
interpretiert. Ein Array ist also im Grunde nichts anderes als ein
typisierter Zeiger auf einen Speicherbereich.
Genau wie bei Arrays können wir mit Zeigern
nicht nur das erste Element, auf das er zeigt, verändern,
sondern durch Indizes in eckigen Klammern auch im Speicherbereich
dahinter liegende Elemente.
Mit Zeigern lässt sich auch rechnen. p
zeigt
ursprünglich auf a[0]. Der Befehl p=p+1
würde unseren Zeiger um vier Bytes auf a[1]
weiterbewegen, da der Typ int
auf
32-Bit Maschinen vier Bytes groß ist. Beim Rechnen und
Indizieren
mit Zeigern kommt also der Typ des Zeigers durchaus zum Tragen.
Häufig sieht man in C und C++ die Notation
*p++
= x;
Das bedeutet im Klartext: Weise dem,
worauf p zeigt den Wert x
zu und bewege den Zeiger danach ein Arrayelement weiter.
Funktionen
Bisher haben wir einer Funktionen immer Parameter
übergeben und eventuell einen Wert zurückgeliefert.
Wenn wir
mehrere Werte zurückliefern oder Parameter in ihrem Wert
ändern wollten, hatten wir bisher dazu
keine Möglichkeit. Mit Zeigern funktioniert es:
void
pointer(int*
x)
{
// Wert von x quadrieren
*x = (*x) * (*x);
}
Wer möchte, kann die
Klammern auch weglassen. Aufgerufen werden kann diese Funktion danach
z.B. so:
//
Variable im Speicher anlegen
int x = 2;
// x mit Hilfe von Zeiger
verändern
pointer(&x);
Nach Abarbeiten dieser beiden Zeilen steht in x,
wie erwartet, der Wert 4.
Im Beispielcode ist noch eine Alternative zum
Übergeben
eines Parameters als Zeiger durch eine sogenannte Referenz
aufgeführt. Referenzen sind im Grunde Zeiger, nur in anderer,
manchmal ebenso verwirrender, Notation. Daher möchte ich hier
nicht genauer darauf eingehen.
NULL
Ein Zeiger, der auf nichts zeigt, besitzt den Wert NULL.
Dieser ist in der Standard-Headerdatei memory.h deklariert.
Der Vergleich auf NULL ist z.B. sinnvoll um festzustellen, ob überhaupt Speicher belegt wurde.
zurück