Verwendung des Pfeiloperators (->) in C

Lesezeit: 6 Minuten

Benutzeravatar von Mohit Deshpande
Mohit Deshpande

Ich lese ein Buch mit dem Titel „Teach Yourself C in 21 Days“ (Ich habe bereits Java und C# gelernt, also bewege ich mich viel schneller). Ich las das Kapitel über Zeiger und die -> (Pfeil) Operator kam ohne Erklärung. Ich denke, dass es verwendet wird, um Mitglieder und Funktionen aufzurufen (wie das Äquivalent der . (Punkt)-Operator, aber für Zeiger statt Mitglieder). Aber ich bin mir nicht ganz sicher.

Könnte ich bitte eine Erklärung und ein Codebeispiel bekommen?

  • Holen Sie sich ein besseres Buch. norvig.com/21-days.html

    – Josperry

    4. April 2010 um 16:35 Uhr

  • qrdl ist richtig – die Bücher “Lerne X in Y Tagen” sind im Allgemeinen Müll. Neben K&R würde ich auch Pratas „C Primer Plus“ empfehlen, der tiefer in die Tiefe geht als K&R.

    – J.Taylor

    29. April 2011 um 23:29 Uhr

  • @Steve Diese Frage befasst sich mit C++. Es als a zu bezeichnen, verursachte bei mir einige Verwirrung, als ich anfing, in dieser anderen Antwort über das Überladen von Operatoren zu lesen, was in C nicht relevant ist.

    – Johannes

    13. Mai 2013 um 19:42 Uhr


  • @Belton Die Hard-Way-Serien sind schlecht, der Typ sagt Dinge, die nicht einmal relevant waren, als er das Buch schrieb, und er kümmert sich nicht um gute Praktiken.

    – Balint

    25. Juni 2017 um 19:51 Uhr

  • Er hat nicht gesagt, dass es ein großartiges Buch war! Es ist nur das Buch, das er aus irgendeinem Grund gerade gelesen hat. Vielleicht bekommt er viel davon und er plant, ein besseres zu lesen, wenn er fertig ist. Solche Kommentare nerven

    – uh_big_mike_boi

    28. Juni 2019 um 14:14 Uhr

foo->bar ist äquivalent zu (*foo).bardh es wird das Mitglied angerufen bar aus der Struktur that foo verweist auf.

  • Es ist erwähnenswert, dass, wenn der Dereferenzierungsoperator wie in Pascal postfixiert worden wäre, die -> Betreiber überhaupt nicht benötigt worden wäre, da es der viel besser lesbaren gleichwertig gewesen wäre foo*.bar. Das ganze Durcheinander von typdefinierenden Funktionen mit all den zusätzlichen Klammern wäre auch vermieden worden.

    – Benutzer207421

    26. Januar 2015 um 6:04 Uhr


  • So würde foo*.bar und (*foo).bar beide sind äquivalent zu foo->bar? Wie wäre es mit Foo myFoo = *foo; myFoo.bar?

    – Aaron Franke

    9. Januar 2019 um 8:21 Uhr

  • Nein, sagt er nur WENN Die Schöpfer von C hätten den Dereferenzierungsoperator als POSTfix-Operator anstelle von PREfix gemacht, dann wäre es einfacher gewesen. Aber es IST ein Präfixoperator in C.

    – Reichhart

    16. März 2019 um 9:59 Uhr


  • @ user207421 Könnten Sie bitte eine kurze Beschreibung oder einen Link zu den “typedef-ing-Funktionen mit all den zusätzlichen Klammern” geben, die Sie erwähnen? Vielen Dank.

    – RoG

    27. Mai 2019 um 6:24 Uhr

  • @ user207421 Nee, es würde mehr Eltern verursachen. Bisher gibt es Priorität von () und [] nach rechts über * nach links. Wenn sie alle auf einer Seite stehen, haben Sie mehr Eltern. Dasselbe in Ausdrücken, wegen Konflikt mit dem Multiplikationsoperator. Pascal ^ könnte eine Option sein, aber es war für Bitoperationen reserviert, noch mehr Eltern.

    – Swift – Friday Pie

    22. Oktober 2019 um 6:32 Uhr


Jacks Benutzeravatar
Jack

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.

struct foo
{
  int x;
  float y;
};

struct foo var;
struct foo* pvar;
pvar = malloc(sizeof(struct foo));

var.x = 5;
(&var)->y = 14.3;
pvar->y = 22.4;
(*pvar).x = 6;

Das ist es!

  • Da pvar nicht initialisiert ist, wie würden Sie es initialisieren, wenn Sie möchten, dass pvar auf eine neue Struktur zeigt, die es nicht ist pvar = &var?

    – CMCDragonkai

    26. September 2015 um 14:27 Uhr

  • Die Frage bezog sich speziell auf C, das keine Klassen oder Referenzvariablen hat.

    Benutzer2442944

    19. Dezember 2016 um 19:34 Uhr

  • hmm, sollten Sie nicht malloc machen, bevor Sie in pvar schreiben struct foo* pvar; ?? pvar->y in nicht zugeordneten Speicherplatz schreiben!

    – Zibri

    21. März 2018 um 8:46 Uhr

  • pvar-Initialisierung: Initialisieren Sie alle Mitglieder manuell auf einige Standardwerte, die Sie haben möchten, oder verwenden Sie so etwas wie calloc(), wenn Nullfüllung für Sie in Ordnung wäre.

    – Reichhart

    16. März 2019 um 10:03 Uhr

  • sollte es nicht sein: pvar = malloc(sizeof(struct foo)) oder malloc(sizeof(*pvar))??

    – Juri Aps

    14. Juli 2019 um 2:01 Uhr

Ich würde den Antworten nur das “Warum?” hinzufügen.

. ist ein Standardmitgliedszugriffsoperator, der eine höhere Priorität hat als * Zeigeroperator.

Wenn Sie versuchen, auf die Interna einer Struktur zuzugreifen, und Sie es als geschrieben haben *foo.bar dann würde der Compiler denken, er möchte ein ‘bar’-Element von ‘foo’ (was eine Adresse im Speicher ist) und offensichtlich hat diese bloße Adresse keine Mitglieder.

Daher müssen Sie den Compiler bitten, zuerst mit zu dereferenzieren (*foo) und dann auf das Member-Element zugreifen: (*foo).barwas etwas ungeschickt zu schreiben ist, also haben sich die guten Leute eine Kurzversion ausgedacht: foo->bar Das ist eine Art Mitgliedszugriff durch Zeigeroperator.

a->b ist nur kurz für (*a).b in jeder Hinsicht (dasselbe gilt für Funktionen: a->b() ist kurz für (*a).b()).

foo->bar ist nur eine Abkürzung für (*foo).bar. Das ist alles dazu.

Nun, ich muss auch etwas hinzufügen. Struktur unterscheidet sich ein wenig von Array, da Array ein Zeiger ist und Struktur nicht. Also sei vorsichtig!

Nehmen wir an, ich schreibe dieses nutzlose Stück Code:

#include <stdio.h>

typedef struct{
        int km;
        int kph;
        int kg;
    } car;

int main(void){

    car audi = {12000, 230, 760};
    car *ptr = &audi;

}

Hier Zeiger ptr zeigt auf die Adresse (!) der Strukturvariablen audi hat aber neben der Adressstruktur auch eine Stück Daten (!)! Das erste Mitglied der Stück Daten hat die gleiche Adresse wie die Struktur selbst und Sie können ihre Daten erhalten, indem Sie nur einen solchen Zeiger dereferenzieren *ptr (keine Klammern).

Wenn Sie jedoch auf ein anderes Element als das erste zugreifen möchten, müssen Sie einen Bezeichner wie hinzufügen .km, .kph, .kg die nichts anderes als Offsets zur Basisadresse der sind Stück Daten

Aber wegen der Vorrang du kannst nicht schreiben *ptr.kg als Zugangsbetreiber . wird vor dem Dereferenzierungsoperator ausgewertet * und du würdest bekommen *(ptr.kg) was nicht möglich ist, da der Zeiger keine Mitglieder hat! Und der Compiler weiß das und wird daher einen Fehler ausgeben, z. B.:

error: ‘ptr’ is a pointer; did you mean to use ‘->’?
  printf("%d\n", *ptr.km);

Stattdessen verwenden Sie diese (*ptr).kg und Sie zwingen den Compiler dazu 1 Dereferenzieren Sie den Zeiger und ermöglichen Sie den Zugriff auf die Stück Daten und 2 Sie fügen einen Versatz (Bezeichner) hinzu, um das Mitglied auszuwählen.

Überprüfen Sie dieses Bild, das ich gemacht habe:

Geben Sie hier die Bildbeschreibung ein

Aber wenn Sie Mitglieder verschachtelt hätten, wäre diese Syntax unlesbar und daher -> wurde vorgestellt. Ich denke, Lesbarkeit ist der einzige berechtigte Grund, es so zu verwenden ptr->kg ist viel einfacher zu schreiben als (*ptr).kg.

Lass uns das jetzt anders schreiben, damit du den Zusammenhang klarer siehst. (*ptr).kg(*&audi).kgaudi.kg. Hier habe ich zuerst die Tatsache verwendet, dass ptr ist ein “Adresse von audi dh &audi und Tatsache, dass “Hinweis” & und “dereferenzieren” * Operatoren heben sich gegenseitig auf.

Benutzeravatar von Donald Duck
Donald Duck

struct Node {
    int i;
    int j;
};
struct Node a, *p = &a;

Hier der Zugriff auf die Werte von i und j Wir können die Variable verwenden a und der Zeiger p folgendermaßen: a.i, (*p).i und p->i sind alle gleich.

Hier . ist ein “Direct Selector” und -> ist ein “indirekter Selektor”.

1427090cookie-checkVerwendung des Pfeiloperators (->) in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy