Zurück zu: C Tutorial
Zeiger erstellen
Im vorigen Kapitel hast du gelernt, dass wir die Speicheradresse einer Variablen mit dem Referenzoperator &
ermitteln können:
Beispiel
int myAge = 43; // an int variable
printf("%d", myAge); // Outputs the value of myAge (43)
printf("%p", &myAge); // Outputs the memory address of myAge (0x7ffe5367e044)
Ein Zeiger ist eine Variable, die die Speicheradresse einer anderen Variablen als ihren Wert speichert.
Eine Zeigervariable zeigt auf einen Datentyp (wie int) desselben Typs und wird mit dem Operator *
erstellt.
Dem Zeiger wird die Adresse der Variable zugewiesen, mit der Sie arbeiten:
Beispiel
int myAge = 43; // An int variable
int* ptr = &myAge; // A pointer variable, with the name ptr, that stores the address of myAge
// Output the value of myAge (43)
printf("%d\n", myAge);
// Output the memory address of myAge (0x7ffe5367e044)
printf("%p\n", &myAge);
// Output the memory address of myAge with the pointer (0x7ffe5367e044)
printf("%p\n", ptr);
Beispiel erklärt
Erstellen Sie eine Zeigervariable mit dem Namen ptr
, die auf eine int
Variable (myAge
) zeigt. Beachten Sie, dass der Typ des Zeigers mit dem Typ der Variablen übereinstimmen muss, mit der Sie arbeiten (int
in unserem Beispiel).
Verwenden Sie den &
Operator, um die Speicheradresse der Variable myAge
zu speichern und sie dem Zeiger zuzuweisen.
Jetzt enthält ptr
den Wert der Speicheradresse von myAge
.
Dereferenzierung
Im obigen Beispiel haben wir die Zeigervariable verwendet, um die Speicheradresse einer Variablen zu erhalten (zusammen mit dem Referenzoperator &
verwendet).
Sie können den Wert der Variablen, auf die der Zeiger zeigt, auch abrufen, indem Sie den Operator *
(den Dereferenzierungsoperator) verwenden:
Beispiel
int myAge = 43; // Variable declaration
int* ptr = &myAge; // Pointer declaration
// Reference: Output the memory address of myAge with the pointer (0x7ffe5367e044)
printf("%p\n", ptr);
// Dereference: Output the value of myAge with the pointer (43)
printf("%d\n", *ptr);
Beachten Sie, dass das
*
Zeichen hier verwirrend sein kann, da es in unserem Code zwei verschiedene Dinge bewirkt:
- Bei Verwendung in der Deklaration (
int* ptr
) wird eine Zeigervariable erstellt.- Wenn es nicht in der Deklaration verwendet wird, fungiert es als Dereferenzierungsoperator.
Gut zu wissen: Es gibt zwei Möglichkeiten, Zeigervariablen in C zu deklarieren:
int* myNum; int *myNum;
Hinweise zu Zeigern
Zeiger sind eines der Dinge, durch die sich C von anderen Programmiersprachen wie Python und Java unterscheidet.
Sie sind in C wichtig, weil sie es uns ermöglichen, die Daten im Speicher des Computers zu manipulieren. Dies kann den Code reduzieren und die Leistung verbessern. Wenn Sie mit Datenstrukturen wie Listen, Bäumen und Graphen vertraut sind, sollten Sie wissen, dass Zeiger für deren Implementierung besonders nützlich sind. Und manchmal müssen Sie sogar Zeiger verwenden, beispielsweise bei der Arbeit mit Dateien und der Speicherverwaltung.
Aber Vorsicht: Zeiger müssen mit Vorsicht behandelt werden, da die Möglichkeit besteht, dass in anderen Speicheradressen gespeicherte Daten beschädigt werden.
Zeiger und Arrays
Sie können auch Zeiger verwenden, um auf Arrays zuzugreifen.
Betrachten Sie das folgende Array von Ganzzahlen:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
Im Kapitel zu Arrays haben Sie gelernt, dass Sie die Array Elemente mit einer For
Schleife durchlaufen können:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", myNumbers[i]);
}
Ergebnis:
25
50
75
100
Anstatt den Wert jedes Array-Elements auszudrucken, drucken wir die Speicheradresse jedes Array-Elements aus:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4; i++) {
printf("%p\n", &myNumbers[i]);
}
Ergebnis:
0x7ffe70f9d8f0
0x7ffe70f9d8f4
0x7ffe70f9d8f8
0x7ffe70f9d8fc
Beachten Sie, dass die letzte Zahl der Speicheradressen der einzelnen Elemente unterschiedlich ist und den Wert 4 hinzufügt.
Dies liegt daran, dass die Größe eines int
Typs normalerweise 4 Byte beträgt. Denken Sie daran:
Beispiel
// Create an int variable
int myInt;
// Get the memory size of an int
printf("%lu", sizeof(myInt));
Ergebnis:
4
Aus dem obigen „Speicheradressenbeispiel“ können Sie ersehen, dass der Compiler für jedes Array-Element 4 Byte Speicher reserviert, was bedeutet, dass das gesamte Array 16 Byte (4 x 4) Speicherplatz beansprucht:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
// Get the size of the myNumbers array
printf("%lu", sizeof(myNumbers));
Ergebnis:
16
Wie hängen Zeiger mit Arrays zusammen?
Ok, was ist also die Beziehung zwischen Zeigern und Arrays? Nun, in C ist der Name eines Arrays eigentlich ein Zeiger auf das erste Element des Arrays.
Verwirrt? Versuchen wir, dies besser zu verstehen und verwenden noch einmal unser obiges „Speicheradressenbeispiel“.
Die Speicheradresse des ersten Elements ist identisch mit dem Namen des Arrays:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
// Get the memory address of the myNumbers array
printf("%p\n", myNumbers);
// Get the memory address of the first array element
printf("%p\n", &myNumbers[0]);
Ergebnis:
0x7ffe70f9d8f0
0x7ffe70f9d8f0
Dies bedeutet im Wesentlichen, dass wir mit Arrays über Zeiger arbeiten können!
Wie? Da myNumbers ein Zeiger auf das erste Element in myNumbers ist, können Sie den *
Operator verwenden, um darauf zuzugreifen:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
// Get the value of the first element in myNumbers
printf("%d", *myNumbers);
Ergebnis:
25
Um auf die restlichen Elemente in myNumbers zuzugreifen, können Sie den Zeiger/das Array erhöhen (+1, +2 usw.):
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
// Get the value of the second element in myNumbers
printf("%d\n", *(myNumbers + 1));
// Get the value of the third element in myNumbers
printf("%d", *(myNumbers + 2));
// and so on..
Ergebnis:
50
75
Oder durchlaufen Sie es in einer Schleife:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
int *ptr = myNumbers;
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", *(ptr + i));
}
Ergebnis:
25
50
75
100
Es ist auch möglich, den Wert von Array Elementen mit Zeigern zu ändern:
Beispiel
int myNumbers[4] = {25, 50, 75, 100};
// Change the value of the first element to 13
*myNumbers = 13;
// Change the value of the second element to 17
*(myNumbers +1) = 17;
// Get the value of the first element
printf("%d\n", *myNumbers);
// Get the value of the second element
printf("%d\n", *(myNumbers + 1));
Ergebnis:
13
17
Diese Art, mit Arrays zu arbeiten, mag etwas übertrieben erscheinen. Besonders bei einfachen Arrays wie in den obigen Beispielen. Bei großen Arrays kann es jedoch viel effizienter sein, mit Zeigern auf Arrays zuzugreifen und sie zu bearbeiten.
Außerdem gilt der Zugriff auf zweidimensionale Arrays mit Zeigern als schneller und einfacher.
Und da Zeichenfolgen eigentlich Arrays sind, können Sie auch Zeiger verwenden, um auf Zeichenfolgen zuzugreifen.
Für den Moment ist es gut, dass Sie wissen, wie das funktioniert. Aber wie wir im vorherigen Kapitel erklärt haben, müssen Zeiger mit Vorsicht behandelt werden, da es möglich ist, andere im Speicher gespeicherte Daten zu überschreiben.