Ein Pointer (deutsch: Zeiger) ist eine Variable, die nicht einen Wert, sondern die Speicheradresse eines anderen Werts speichert. Statt direkt auf die Daten zuzugreifen, zeigt der Pointer auf die Stelle im Arbeitsspeicher, an der die Daten liegen.

So funktioniert ein Pointer

Jede Variable belegt Speicherplatz. Ein Pointer speichert die Adresse dieses Speicherplatzes. Den Vorgang, über die Adresse an den eigentlichen Wert zu gelangen, nennt man Dereferenzierung — in C mit dem Sternoperator: *ptr.

int x = 42;    /* normale Variable */
int *ptr = &x; /* Pointer auf die Adresse von x */
printf("%d", *ptr); /* gibt 42 aus */

Ein Pointer kann auf NULL gesetzt werden, um auszudrücken, dass er auf nichts zeigt. Bevor man einen Pointer dereferenziert, sollte man prüfen, ob er gültig ist — sonst drohen Abstürze oder Sicherheitslücken.

Wofür Pointer gebraucht werden

  • Effiziente Übergabe: Große Datenstrukturen werden per Adresse übergeben, statt sie zu kopieren.
  • Dynamische Datenstrukturen: Verkettete Listen, Bäume und Graphen verbinden Knoten über Pointer.
  • Direkter Speicherzugriff: In der Systemprogrammierung steuert man Speicher und Hardware über Adressen.
  • Funktionspointer: Funktionen lassen sich als Werte speichern und aufrufen (z. B. für Callbacks).

Risiken und moderne Alternativen

Pointer sind mächtig, aber fehleranfällig: Ein dangling pointer zeigt auf bereits freigegebenen Speicher, ein wild pointer auf eine zufällige Adresse. Überläufe und falsche Dereferenzierung sind klassische Ursachen für Sicherheitslücken.

Moderne Sprachen entschärfen das Konzept: C und C++ arbeiten direkt mit Pointern, Rust nutzt Referenzen mit einem strengen Borrow-Checker, Go erlaubt Pointer ohne Zeigerarithmetik, und Java sowie C# verwenden sichere Referenzen statt roher Adressen. Eng verwandt sind Stack, Call Stack und Arbeitsspeicher.