Der Nullzeiger
Manchmal hat ein Zeiger nichts, worauf er zeigen könnte. Stell dir eine Funktion vor, die ein Array von Temperaturen nach dem ersten Frost durchsucht, einer Temperatur unter null, und seine Adresse zurückgibt. Was soll sie zurückgeben, wenn die ganze Woche kein Frost war? Dafür hat C den Wert NULL, den Nullzeiger: einen Zeiger, der nirgendwohin zeigt.
Diese Funktion gibt eine Adresse zurück, also ist ihr Rückgabetyp int *. &zahlen[i] ist die Adresse des Elements mit dem Index i:
int *finde_negative(int *zahlen, int anzahl) {
for (int i = 0; i < anzahl; i++) {
if (zahlen[i] < 0) {
return &zahlen[i];
}
}
return NULL;
}Warum gibt sie eine Adresse zurück und nicht die Temperatur selbst? Weil eine Zahl nicht „es gibt keine“ sagen kann: Jede Zahl, die die Funktion zurückgäbe, könnte eine echte Temperatur sein. Ein Zeiger kann es, denn NULL ist die Adresse keiner Variablen.
Bevor du einen Zeiger verwendest, der NULL sein kann, prüfe ihn mit if:
#include <stdio.h>
int *finde_negative(int *zahlen, int anzahl) {
for (int i = 0; i < anzahl; i++) {
if (zahlen[i] < 0) {
return &zahlen[i];
}
}
return NULL;
}
int main(void) {
int woche[] = {3, 1, -2, 0, -4};
int *frost = finde_negative(woche, 5);
if (frost != NULL) {
printf("Erster Frost: %d\n", *frost);
} else {
printf("Kein Frost\n");
}
return 0;
}Das gibt aus:
Erster Frost: -2Warum prüfen? Über NULL zu lesen oder zu schreiben ist ein Fehler, denn dort gibt es keine Variable. Auf einem Computer stürzt ein solches Programm meist ab, oft mit der Meldung Segmentation fault. Hier im Browser stoppt das Lesen über NULL das Programm mit dem Fehler RuntimeError: unreachable, demselben Fehler wie bei einem Index hinter dem Ende eines Arrays. Er sagt nicht, was schiefgelaufen ist. Wenn du ihn in einem Programm mit Zeigern siehst, suche also nach einem Zeiger, der NULL sein kann.
NULL ist auch ein guter Anfangswert für einen Zeiger, der noch auf nichts zeigen kann: int *gefunden = NULL;. Ein Zeiger ganz ohne Wert, int *p;, ist hier ein Kompilierfehler, sobald du ihn verwendest (variable 'p' is uninitialized when used here), wie jede Variable ohne Wert.
Noch eine Regel für Funktionen, die einen Zeiger zurückgeben: Gib nur Adressen von Dingen zurück, die noch existieren, wenn die Funktion endet, etwa die Elemente des Arrays, das sie bekommen hat. Die lokalen Variablen einer Funktion verschwinden, wenn sie endet, gib also niemals ihre Adressen zurück.
So schreibst du es:
Anweisungen
- 1
Im Array
reiheist1ein besetzter Platz und0ein freier. Das Programm lässt sich nicht kompilieren: Wenn kein Platz frei ist, endet die Funktionfinde_freien_platzohnereturn. Füge an ihrem Ende, nach der Schleife,return NULL;hinzu. Das Programm gibt dann zweimalGebuchtaus. - 2
Eine dritte Person kommt ins Kino. Rufe in
mainein drittes Malplatz_buchen(reihe, 4);auf. Das Programm gibt zweimalGebuchtaus und bricht dann mitRuntimeError: unreachableab: Die Reihe ist voll, also hatfinde_freien_platzNULLzurückgegeben, undplatz_buchenhat versucht, darüber zu schreiben. Korrigiereplatz_buchen: WennplatzgleichNULList, gibt die FunktionAusverkauftaus und ändert nichts; sonst bucht sie den Platz wie bisher. Das Programm gibtGebucht,GebuchtundAusverkauftaus.