MINT lernen

Zeiger

Wie kann eine Variable auf eine andere zeigen — und sie ändern, ohne ihren Namen zu kennen?

1

Variablen, die auf Variablen zeigen

Ein Zeiger ist eine Variable, deren Wert eine Adresse ist.

C · zeiger.c
#include <stdio.h>

int main(void) {
    int x = 10;
    int *p = &x;              // p speichert die Adresse von x

    printf("&x = %p\n", (void *) &x);
    printf("p  = %p\n", (void *) p);
    printf("*p = %d\n", *p);  // Wert an dieser Adresse lesen

    *p = 7;                   // über p in x schreiben
    printf("x  = %d\n", x);
    return 0;
}
Konsole
$ gcc -Wall zeiger.c -o zeiger
$ ./zeiger
&x = 0x7fffecea352c
p  = 0x7fffecea352c
*p = 10
x  = 7
  • Deklarieren:int *p; — p ist ein „Zeiger auf int“.
  • Adresse zuweisen:p = &x; — p zeigt jetzt auf x, p und &x sind gleich.
  • Dereferenzieren:*p liest den Wert an der Adresse, auf die p zeigt.
  • Schreiben:*p = 7; ändert x, ohne dass x im Befehl vorkommt.
  • NULL:int *p = NULL; — p zeigt auf nichts; *p bringt das Programm dann zum Absturz (Segmentation fault).
  • Passender Typ:double *q = &x; mit int x → gcc meldet „incompatible pointer type“.
  • Zwei Bedeutungen von *:in der Deklaration: „ist ein Zeiger“, im Ausdruck: „gehe zur Adresse“.

Ziehe die orange Pfeilspitze von p auf eine der Variablen oder auf NULL (Tastatur: Pfeilspitze fokussieren, dann Pfeiltasten). Beobachte, wie sich p, *p und die anderen Ausdrücke ändern, und schreibe mit *p = 42 durch den Zeiger.

Zeiger umhängen

C · aktueller Zustand

Halte fest: p ist eine Adresse, *p ist der Wert, der dort steht. Wer über *p schreibt, ändert die Variable, auf die p gerade zeigt — ein NULL-Zeiger zeigt auf nichts, dort darf man weder lesen noch schreiben.

Merke

Zeiger: int *p = &x; speichert die Adresse von x. *p ist der Wert an dieser Adresse — lesen und schreiben. NULL bedeutet: zeigt auf nichts.

2

Zeiger als Parameter

Parameter sind Kopien — bekommt eine Funktion aber Adressen, kann sie die Variablen des Aufrufers ändern.

C · tausch.c
#include <stdio.h>

void tausche(int *a, int *b) {
    int hilf = *a;
    *a = *b;
    *b = hilf;
}

int main(void) {
    int x = 3, y = 8;
    tausche(&x, &y);          // Adressen übergeben
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
Konsole
$ ./tausch
x = 8, y = 3
  • Ohne Zeiger:void tausche(int a, int b) tauscht nur die Kopien — x = 3, y = 8 bleibt.
  • Parameter:int *a nimmt eine Adresse entgegen; *a = … schreibt ins Original.
  • Aufruf:tausche(&x, &y) — Adressen übergeben, nicht Werte.
  • Kopie der Adresse:auch die Adresse wird kopiert, zeigt aber auf dieselbe Speicherstelle.
  • scanf:scanf("%d", &x) braucht die Adresse, damit es den gelesenen Wert in x schreiben kann.
  • Ohne &:scanf("%d", x) → -Wall warnt „expects argument of type 'int *'“, beim Start droht ein Absturz.
Merke

Zeiger als Parameter: Parameter als int *a deklarieren, mit &x aufrufen, innen mit *a arbeiten — so ändert die Funktion das Original.

3

Allgemeine Hinweise

Zeiger immer initialisieren

int *p; zeigt irgendwohin. Weise erst &x oder NULL zu, bevor du *p benutzt.

Der Stern gilt nur für einen Namen

Bei int *p, q; ist nur p ein Zeiger — q ist ein ganz normaler int.

Vor dem Dereferenzieren prüfen

if (p != NULL) schützt vor dem Absturz, wenn ein Zeiger (noch) auf nichts zeigt.

Videos