Zeiger (Pointer)

0

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.

Nach oben scrollen