Es handelt sich um eine Eigenart von C, die Anfänger oft zum Stolpern bringt, sich aber wie Magie anfühlt, sobald es Klick macht: Man kann ein Dutzend Zeiger haben, die alle auf die gleiche Speicheradresse starren.
Betrachten Sie dieses Szenario. Sie deklarieren eine Ganzzahl „i“. Dann deklarieren Sie drei Zeiger „p“, „q“ und „r“. Sie weisen sie alle der Adresse „i“ zu.
„c
int i;
int p, q, *r;
p = &i;
q = &i;
r = p;
„
Schauen Sie sich die letzte Zeile an. „r“ muss nicht direkt etwas über „i“ wissen. Es zeigt einfach auf das, worauf „p“ verweist. Und „p“ zeigt auf „i“. „r“ zeigt also auch auf „i“.
Der Zuweisungsoperator kopiert hier die Adresse, nicht den Wert. Wenn Sie „r = p“ ausführen, kopieren Sie nicht die ganze Zahl in „i“. Sie kopieren den Speicherort, den „p“ enthält.
Nachdem dieser Code ausgeführt wurde, hat „i“ im Wesentlichen vier Namen. Sie können über „i“ darauf zugreifen. Sie können über „p“ darauf zugreifen. Sie können über „ q“ darauf zugreifen. Oder Sie können über „*r“ darauf zugreifen.
Es gibt keine technische Grenze dafür, wie viele Zeiger Sie auf diese Weise stapeln können.
Warum das wichtig ist
Dies ist nicht nur eine akademische Syntax. Es verändert Ihre Einstellung zum Datenfluss.
In Sprachen mit strengen Objektreferenzen wird durch das Kopieren eines Objekts häufig eine neue Instanz im Speicher erstellt. In C ist das Kopieren eines Zeigers kostengünstig. Es ist nur eine Speicheradresse. Schnell. Winzig.
Dadurch können mehrere Teile Ihres Codes dieselben Daten ohne Duplizierung bearbeiten. Ändern Sie „p“ und „ q“ sieht die Änderung sofort.
Sie erstellen Aliase für den Speicher.
Das Risiko eines Alias
Hier wird der „coole Aspekt“ zur Belastung.
Wenn „p“, „q“ und „r“ alle auf „i“ zeigen, kann jeder von ihnen „i“ ändern.
„c
*p = 10;
„
Jetzt ist „i“ 10. „q“ ist 10. „ r“ ist 10.
Aber was ist, wenn Sie vergessen, dass „r“ auch „i“ beobachtet? Sie könnten annehmen, dass „i“ stabil ist, weil Sie es nicht direkt berührt haben. Sie haben nur „*q“ berührt.
Es handelt sich um eine gemeinsam genutzte Ressource. Und gemeinsam genutzte Ressourcen sind der Ort, an dem es zu Rennbedingungen und unerwarteten Überschreibungen kommt.
So verhindern Sie unbeabsichtigte Nebenwirkungen
Wenn Sie sicherstellen möchten, dass ein Zeiger nicht versehentlich Daten überschreibt, die für einen anderen Zeiger bestimmt sind, verwenden Sie „const“.
„c
const int *r = &i;
„
Jetzt kann „r“ „i“ lesen. Es kann darauf hinweisen. Es kann es nicht ändern.
„c
*r = 5; // Compilerfehler
„
Auf diese Weise setzen Sie Grenzen in einer Sprache durch, die Ihnen die manuelle Verwaltung des Speichers anvertraut.
Wo das in die Systemprogrammierung passt
Dieses Muster sieht man überall im Systemcode.
Kernelstrukturen verfügen häufig über mehrere Zeiger auf denselben Steuerblock. Gerätetreiber ordnen dasselbe Hardwareregister unterschiedlichen logischen Namen zu.
Wenn Sie verstehen, dass Zeiger nur Bezeichnungen für Adressen sind, können Sie diese Probleme besser beheben. Wenn der Speicher beschädigt ist, verfolgen Sie die Zeiger. Wer sonst





















