Wie ändert eine Funktion die Variable ihres Aufrufers?
Ein Zeiger in C ist eine Variable, die die Adresse einer anderen Variablen speichert. Mit ihm kann eine Funktion den Wert einer Variablen im Aufrufer ändern, und ohne ihn kann sie das nicht.
Ein Kassenprogramm erhöht zum Beispiel einen Preis um 50 Cent in einer eigenen Funktion. Dafür braucht die Funktion die Adresse des Preises, nicht nur eine Kopie seines Wertes.
Am Ende dieser Lektion
Notiz
Ich kann C-Code lesen und schreiben, der Zeiger benutzt.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Zeiger | eine Variable, die eine Adresse enthält | int *zeiger |
| Adressoperator | liefert die Adresse einer Variablen | &preis |
| Dereferenzierung | greift auf den Wert an einer Adresse zu | *zeiger |
| NULL | ein Zeiger, der auf nichts zeigt | |
| Zeigerarithmetik | Rechnen mit Adressen in Schritten der Elementgröße |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Zeiger speichert die Adresse einer Variablen
Mit &preis fragen Sie nach der Adresse der Variablen preis. Ein Zeiger speichert diese Adresse, zum Beispiel int *zeiger = &preis;.
Mit *zeiger gehen Sie den Weg zurück und lesen oder schreiben den Wert an dieser Adresse. Das nennt man Dereferenzierung. Der Zeiger ist selbst eine Variable mit eigener Adresse.
Beispiel: preis und zeiger im Modellspeicher
| Variable | Adresse im Modell | Inhalt |
|---|---|---|
| preis | 0 | 250 |
| zeiger | 4 | 0, die Adresse von preis |
| *zeiger | über zeiger erreicht | 250, der Wert von preis |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Zeiger im Modellspeicher
# Modell: der Speicher ist ein bytearray, eine Adresse ist ein Index
speicher = bytearray(8)
speicher[0] = 250 # die Variable preis liegt an Adresse 0
zeiger = 0 # ein Zeiger ist nur eine Zahl: die Adresse
speicher[zeiger] = 40 # entspricht *zeiger = 40
print(speicher[0])
# Setzen Sie zeiger auf 3 und schreiben Sie den Wert 7 dorthin.
Mit einem Zeiger ändert eine Funktion fremde Variablen
C übergibt einer Funktion immer eine Kopie. Ändert die Funktion ihren Parameter, bleibt die Variable des Aufrufers unberührt.
Übergeben Sie stattdessen die Adresse mit &preis, dann schreibt die Funktion über *preis direkt in die Variable des Aufrufers. Das Programm unten tut das. Es erhöht den Preis in einer Funktion um 50.
Das Programm zeiger.c
#include <stdio.h>
void erhoehe(int *preis) {
*preis = *preis + 50;
}
int main(void) {
int preis = 250;
int *zeiger = &preis;
*zeiger = 300;
erhoehe(&preis);
printf("Preis %d, über den Zeiger %d\n", preis, *zeiger);
return 0;
}
In den Arbeitsordner wechseln
mkdir -p ~/csys && cd ~/csysHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Programm in eine Datei schreiben
printf '#include <stdio.h>\n\nvoid erhoehe(int *preis) {\n *preis = *preis + 50;\n}\n\nint main(void) {\n int preis = 250;\n int *zeiger = &preis;\n *zeiger = 300;\n erhoehe(&preis);\n printf("Preis %%d, über den Zeiger %%d\\n", preis, *zeiger);\n return 0;\n}\n' > zeiger.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Programm übersetzen
gcc -o zeiger zeiger.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Programm starten
./zeigerHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Zeiger + 1 geht ein ganzes Element weiter
Zählt man zu einem Zeiger eins dazu, geht er nicht ein Byte weiter, sondern ein ganzes Element. Bei einem int-Zeiger sind das vier Bytes. Das heißt Zeigerarithmetik.
So erreicht *(p + 3) das vierte Element eines Arrays. Das Programm unten zeigt es, und die Befehle schreiben, übersetzen und starten es.
Das Programm feld.c
#include <stdio.h>
int main(void) {
int preise[4] = {10, 20, 30, 40};
int *p = preise;
printf("%d %d %d\n", *p, *(p + 1), *(p + 3));
printf("Schritt in Bytes: %td\n", (char *)(p + 1) - (char *)p);
printf("Abstand in Elementen: %td\n", &preise[3] - &preise[0]);
return 0;
}
Das zweite Programm in eine Datei schreiben
printf '#include <stdio.h>\n\nint main(void) {\n int preise[4] = {10, 20, 30, 40};\n int *p = preise;\n printf("%%d %%d %%d\\n", *p, *(p + 1), *(p + 3));\n printf("Schritt in Bytes: %%td\\n", (char *)(p + 1) - (char *)p);\n printf("Abstand in Elementen: %%td\\n", &preise[3] - &preise[0]);\n return 0;\n}\n' > feld.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das zweite Programm übersetzen
gcc -o feld feld.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das zweite Programm starten
./feldHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein häufiger Fehler
Warnung
Viele glauben, zeiger + 1 gehe ein Byte weiter. Bei einem int-Zeiger sind es vier Bytes, bei einem char-Zeiger eines. Prüfen Sie den Typ, bevor Sie Adressen rechnen. Ein Zeiger auf NULL zeigt auf nichts, und sein Zugriff ist in C undefiniert.