Was sind Pointer? Worauf zeigen Pointer? Was ist wenn ich den Wert ändere?

Wird in einem Programm auf einen Wert zugegriffen, erfolgt das implizit über eine Speicher-Adresse. Der Zugriff auf eine Speicheradresse kann mit einem Pointer (Zeiger) erfolgen. Man sagt auch, ein Pointer zeigt auf eine Speicheradresse.

In C haben Pointer einen Typ. Die Deklaration: int *p; kann man lesen als: *p ist vom Typ int, p ist ein Zeiger auf den int-Wert *p. Mit *p kann also auf den int-Wert, auf den der Zeiger p zeigt, zugegriffen werden.

C:

int a, *pa;
a = 123;
pa = &a;
*pa = 456;
printf("%d %d %p\n", a, *pa, pa); // Ausgabe: 456 456 0028fee0

In Zeile 1 wird die int-Variable a sowie ein Zeiger pa auf eine int-Variable deklariert.
In Zeile 3 wird mit dem Adressoperator (&) die Adresse von a bestimmt und dem Zeiger pa zugewiesen. Man sagt, der Zeiger pa zeigt auf a.
In Zeile 4 wird mit dem Inhaltsoperator / Dereferenzierungsoperator (*) der Wert an der Speicherstelle, auf die der Zeiger pa zeigt, verändert. a hat jetzt den Wert 456.
In Zeile 5 wird a, der Inhalt auf den pa zeigt, sowie die Speicheradresse auf die pa zeigt, ausgegeben.

Zeiger auf Arrays:

int *p;
int ar[] = { 1, 4, 9, 16 };
p = ar;
printf("%d %p\n", *p, p); // 1 0028fee0
p++;
printf("%d %p\n", *p, p); // 4 0028fee4

In Zeile 1 wird ein Pointer vom Typ int angelegt.
In Zeile 2 wird das Array ar[] deklariert und initialisiert.
In Zeile 3 wird der Pointer p auf das Array ar[] gesetzt. D.h. p enthält die Speicheradresse von ar[0]. Als Synonym für den Code-Sequenz p = ar; könnte man also theoretisch auch die Code-Sequenz p = &ar[0]; verwenden.
In Zeile 4 wird der Wert von ar[0] und die Speicheradresse von ar[0] ausgegeben.
In Zeile 5 wird der Zeiger p inkrementiert. Er zeigt jetzt also auf ar[1].
In Zeile 6 wird der Wert von ar[1] und die Speicheradresse von ar[1] ausgegeben.

Vergleicht man die zwei ausgegebenen Speicheradressen, sieht man, dass die Differenz 4 beträgt. Dieser Wert entspricht der Byte-Breite eines int-Wertes im Speicher.

Beispiel Pointerarithmetik:

Mittels Pointer und Pointer-Arithmetik lassen sich verschiedene Algorithmen sehr kompakt formulieren. Im folgenden Code-Sample wird eine Methode zur Bestimmung der Länge eines Strings gezeigt.

int strlen(char *s) {
    int len = 0;
    while (*s++) {
        len++;
    }
    return len;
}

Der Methode strlen() wird ein Zeiger auf eine Zeichenkette übergeben.

In Zeile 3 wird mit dem Inhaltsoperator auf das aktuelle Zeichen zugegriffen und als Schleifenbedingung verwendet. Im Anschluss daran wird der Zeiger inkrementiert. Wenn der Zeiger auf das Terminierungssymbol der Zeichenkette zeigt, wird die Schleife beendet. In jedem Iterationsschritt wird der Zähler für die Länge der Zeichenkette um 1 erhöht und nach Beenden der Schleife als Rückgabewert verwendet.

Anmerkung:

Zeichenketten werden in C durch char-Arrays die null-terminiert sind dargestellt. Das letzte Zeichen einer null-terminierten Zeichenkette hat den ASCII-Code 0 (‘\0’). In C gibt es keinen Datentyp für Wahrheitswerte. Der Wert 0 wird in einem boolschen Ausdruck auf false evaluiert. Alle anderen numerischen Werte werden auf true evaluiert.

Beispiel: Inhaltsoperator / Adressoperator:

Der Inhaltsoperator verhält sich invers zum Adressoperator.

*(&a) ≡ a