Ich lese ein Buch mit dem Titel "Teach Yourself C in 21 Days" (ich habe bereits Java und C # gelernt, daher bewege ich mich viel schneller). Ich habe das Kapitel über Zeiger gelesen und der Operator->
(Pfeil) wurde ohne Erklärung angezeigt. Ich denke, dass es verwendet wird, um Mitglieder und Funktionen aufzurufen (wie das Äquivalent des (Punkt-) Operators, aber für Zeiger anstelle von Mitgliedern). Ich bin mir aber nicht ganz sicher..
Könnte ich bitte eine Erklärung und ein Codebeispiel bekommen?
Antworten:
foo->bar
ist äquivalent zu(*foo).bar
, dh es wird das aufgerufene Mitgliedbar
aus der Struktur aufgerufen, diefoo
auf zeigt.quelle
->
Operator überhaupt nicht benötigt worden wäre, da er dem viel besser lesbaren äquivalent gewesen wärefoo*.bar
. Das ganze Durcheinander von Schreibfunktionen mit all den zusätzlichen Klammern wäre ebenfalls vermieden worden.foo*.bar
und(*foo).bar
beides gleichbedeutend mitfoo->bar
? Was ist mitFoo myFoo = *foo; myFoo.bar
?Ja das ist es.
Es ist nur die Punktversion, wenn Sie auf Elemente einer Struktur / Klasse zugreifen möchten, die ein Zeiger anstelle einer Referenz ist.
Das ist es!
quelle
pvar = &var
?a->b
ist(*a).b
in jeder Hinsicht nur kurz für (gleich für Funktionen:a->b()
ist kurz für(*a).b()
).quelle
Ich würde den Antworten nur das "Warum?" Hinzufügen.
.
ist ein Standardzugriffsoperator für Mitglieder, der eine höhere Priorität als der*
Zeigeroperator hat.Wenn Sie versuchen, auf die Interna einer Struktur zuzugreifen, und Sie es so geschrieben haben,
*foo.bar
würde der Compiler denken, dass er ein 'bar'-Element von' foo '(eine Adresse im Speicher) haben möchte, und offensichtlich hat diese bloße Adresse keine Mitglieder.Daher müssen Sie den Compiler bitten, zuerst eine Dereferenzierung mit
(*foo)
und dann auf das Element element: zuzugreifen. Dies(*foo).bar
ist etwas umständlich zu schreiben, sodass die guten Leute eine Kurzversion entwickelt haben:foo->bar
eine Art Elementzugriff per Zeigeroperator.quelle
foo->bar
ist nur eine Abkürzung für(*foo).bar
. Das ist alles dazu.quelle
Hier auf den Zugriff auf die Werte
i
undj
wir können die Variable verwendena
und den Zeigerp
wie folgt:a.i
,(*p).i
undp->i
sind alle gleich.Hier
.
ist ein "Direktwähler" und->
ein "Indirekter Selektor".quelle
Nun, ich muss auch etwas hinzufügen. Die Struktur unterscheidet sich ein wenig vom Array, da das Array ein Zeiger ist und die Struktur nicht. Also sei vorsichtig!
Nehmen wir an, ich schreibe diesen nutzlosen Code:
Hier zeigt der Zeiger
ptr
auf die Adresse ( ! ) Der Strukturvariablen, hataudi
aber neben der Adressstruktur auch einen Datenblock ( ! )! Das erste Mitglied des Datenblocks hat dieselbe Adresse wie die Struktur selbst, und Sie können die Daten abrufen, indem Sie nur einen Zeiger wie diesen dereferenzieren*ptr
(keine geschweiften Klammern) .Aber Wenn Sie ein anderes Mitglied als das erste Acess wollen, müssen Sie einen Bezeichner hinzufügen wie
.km
,.kph
,.kg
die nichts mehr als Offsets auf die Basisadresse des Datenblock ...Aufgrund der Vorrangstellung können Sie jedoch nicht schreiben,
*ptr.kg
da der Zugriffsoperator.
vor dem Dereferenzierungsoperator ausgewertet wird*
und Sie erhalten,*(ptr.kg)
was nicht möglich ist, da der Zeiger keine Mitglieder hat! Und der Compiler weiß das und wird daher einen Fehler ausgeben, zB:Stattdessen verwenden Sie diese
(*ptr).kg
und Sie Compiler erzwingen 1. den Zeiger dereferenzieren und ermöglichen acess zum Teil der Daten und zweiten Sie einen Offset (Bezeichner) in dem das Element zu wählen.Überprüfen Sie dieses Bild, das ich gemacht habe:
Wenn Sie jedoch verschachtelte Mitglieder hätten, wäre diese Syntax unlesbar und wurde daher
->
eingeführt. Ich denke, Lesbarkeit ist der einzige berechtigte Grund für die Verwendung, da diesptr->kg
viel einfacher zu schreiben ist als(*ptr).kg
.Lassen Sie uns dies jetzt anders schreiben, damit Sie den Zusammenhang klarer sehen.
(*ptr).kg
⟹(*&audi).kg
⟹audi.kg
. Hier habe ich zuerst die Tatsache verwendet, dassptr
es sich um eine "Adresse vonaudi
" handelt, dh die&audi
Tatsache, dass "Referenz"&
und "Dereferenzierung"*
-Operatoren gegenseitig aufheben.quelle
Ich musste eine kleine Änderung an Jacks Programm vornehmen, damit es lief. Zeigen Sie nach dem Deklarieren des Strukturzeigers pvar auf die Adresse von var. Ich fand diese Lösung auf Seite 242 von Stephen Kochans Programmierung in C.
Führen Sie dies in vim mit dem folgenden Befehl aus:
Wird ausgegeben:
quelle
%
, um den aktuellen Dateinamen darzustellen. Wie so:!gcc % && ./a.out
quelle
Der
->
Operator macht den Code lesbarer als den*
in einigen Situationen Operator.Wie zum Beispiel: (zitiert aus dem EDK II-Projekt )
Das
_EFI_BLOCK_IO_PROTOCOL
Struktur enthält 4 Funktionszeigerelemente.Angenommen, Sie haben eine Variable
struct _EFI_BLOCK_IO_PROTOCOL * pStruct
und möchten den guten alten*
Operator verwenden, um den Elementfunktionszeiger aufzurufen. Am Ende erhalten Sie folgenden Code:(*pStruct).ReadBlocks(...arguments...)
Mit dem
->
Operator können Sie jedoch folgendermaßen schreiben:pStruct->ReadBlocks(...arguments...)
.Welches sieht besser aus?
quelle
Ausgabe ist 5 5 5
quelle
Dot ist ein Dereferenzierungsoperator und wird verwendet, um die Strukturvariable für einen bestimmten Strukturdatensatz zu verbinden. Z.B :
Auf diese Weise können wir einen Punktoperator verwenden, um auf die Strukturvariable zuzugreifen
quelle
->
. Auch diese Frage wird bereits seit 4,5 Jahren beantwortet.