Wenn Sie über Zeiger nachdenken, ist es hilfreich, Diagramme zu zeichnen . Ein Zeiger ist ein Pfeil, der auf eine Adresse im Speicher zeigt, wobei eine Beschriftung den Typ des Werts angibt. Die Adresse gibt an, wo gesucht werden soll, und der Typ gibt an, was zu nehmen ist. Durch Umsetzen des Zeigers wird die Beschriftung des Pfeils geändert, jedoch nicht die Stelle, an der der Pfeil zeigt.
d
in main
ist ein Zeiger c
vom Typ char
. A char
ist ein Byte Speicher. Wenn d
also dereferenziert wird, erhalten Sie den Wert in diesem einen Byte Speicher. In der folgenden Abbildung repräsentiert jede Zelle ein Byte.
-+----+----+----+----+----+----+-
| | c | | | | |
-+----+----+----+----+----+----+-
^~~~
| char
d
Wenn Sie d
zu int*
besetzen, sagen Sie, dass dies d
wirklich auf einen int
Wert hinweist . Auf den meisten heutigen Systemen int
belegt ein 4 Bytes.
-+----+----+----+----+----+----+-
| | c | ?₁ | ?₂ | ?₃ | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
(int*)d
Wenn Sie dereferenzieren (int*)d
, erhalten Sie einen Wert, der aus diesen vier Speicherbytes bestimmt wird. Der Wert, den Sie erhalten, hängt davon ab, was in diesen Zellen markiert ?
ist und wie ein int
im Speicher dargestellt wird.
Ein PC ist Little-Endian , was bedeutet, dass der Wert von a auf int
diese Weise berechnet wird (vorausgesetzt, er umfasst 4 Bytes) :
* ((int*)d) == c + ?₁ * 2⁸ + ?₂ * 2¹⁶ + ?₃ * 2²⁴
. Wenn Sie also hexadezimal ( printf("%x\n", *n)
) drucken , werden die letzten beiden Ziffern immer angezeigt 35
(das ist der Wert des Zeichens '5'
) , während der Wert Müll ist .
Einige andere Systeme sind Big-Endian-Systeme und ordnen die Bytes in die andere Richtung : * ((int*)d) == c * 2²⁴ + ?₁ * 2¹⁶ + ?₂ * 2⁸ + ?₃
. Auf diesen Systemen beginnt der Wert immer mit 35
hexadezimalem Druck. Einige Systeme haben eine Größe int
, die sich von 4 Bytes unterscheidet. Einige wenige Systeme sind int
unterschiedlich angeordnet, aber es ist äußerst unwahrscheinlich, dass Sie ihnen begegnen.
Abhängig von Ihrem Compiler und Betriebssystem stellen Sie möglicherweise fest, dass der Wert bei jedem Ausführen des Programms unterschiedlich ist oder dass er immer gleich ist, sich jedoch ändert, wenn Sie den Quellcode auch nur geringfügig ändern.
Auf einigen Systemen muss ein int
Wert in einer Adresse gespeichert werden, die ein Vielfaches von 4 (oder 2 oder 8) ist. Dies wird als Ausrichtungsanforderung bezeichnet . Je nachdem, ob die Adresse von c
richtig ausgerichtet ist oder nicht, kann das Programm abstürzen.
Im Gegensatz zu Ihrem Programm geschieht Folgendes, wenn Sie einen int
Wert haben und einen Zeiger darauf nehmen.
int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
| | x | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
p
Der Zeiger p
zeigt auf einen int
Wert. Das Etikett auf dem Pfeil beschreibt korrekt, was sich in der Speicherzelle befindet, sodass beim Dereferenzieren keine Überraschungen auftreten.