wake-up-neo.com

Pfeiloperator (->) Verwendung in C

Ich lerne gerade C, indem ich ein gutes Einsteigerbuch mit dem Titel "Teach Yourself C in 21 Tagen" lese (ich habe bereits Java und C # gelernt, daher bewege ich mich viel schneller) Lesen Sie das Kapitel über Zeiger und das -> (Pfeil) Operator kam ohne Erklärung. Ich denke, dass es verwendet wird, um Mitglieder und Funktionen aufzurufen (wie das Äquivalent des . (Punkt) -Operator, 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?

234
Mohit Deshpande

foo->bar ist äquivalent zu (*foo).bar, d.h. es wird das Mitglied mit dem Namen bar aus der Struktur abgerufen, auf die foo zeigt.

426
sepp2k

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;     // 5
  float y;
};

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

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

Das ist es!

116
Jack

a->b Steht in jeder Hinsicht für (*a).b (Dasselbe gilt für Funktionen: a->b() steht für (*a).b()).

30
Peter Alexander

Ich würde einfach zu den Antworten das "Warum?" Hinzufügen.

. ist ein Standardzugriffsoperator für Mitglieder mit einer höheren Priorität als * Zeigeroperator.

Wenn Sie versuchen, auf die Interna einer Struktur zuzugreifen und sie als *foo.bar dann würde der Compiler denken, ein 'bar'-Element von' foo '(das eine Adresse im Speicher ist) zu wollen und offensichtlich hat diese bloße Adresse keine Mitglieder.

Daher müssen Sie den Compiler bitten, zuerst die Referenz mit (*foo) und dann auf das Element member zugreifen: (*foo).bar, was etwas umständlich zu schreiben ist, daher haben sich die guten Leute eine Kurzfassung ausgedacht: foo->bar ist eine Art Elementzugriff durch einen Zeigeroperator.

21
Lukasz Matysiak

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

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

Um auf die Werte von i und j zuzugreifen, können Sie hier die Variable a und den Zeiger p wie folgt verwenden: a.i, (*p).i und p->i sind alle gleich.

Hier . ist ein "Direct Selector" und -> ist ein "Indirekter Selektor".

10
Jayghosh Wankar
#include<stdio.h>
struct examp{
int number;
};
struct examp a,*b=&a;`enter code here`
main()
{
a.number=5;
/* a.number,b->number,(*b).number produces same output. b->number is mostly used in linked list*/
   printf("%d \n %d \n %d",a.number,b->number,(*b).number);
}

ausgang ist 5 5 5

1
prashanth

Ich musste eine kleine Änderung an Jacks Programm vornehmen, um es zum Laufen zu bringen. Zeigen Sie nach der Deklaration des Strukturzeigers pvar auf die Adresse von var. Ich habe diese Lösung auf Seite 242 von Stephen Kochans Programming in C gefunden.

#include <stdio.h>

int main()
{
  struct foo
  {
    int x;
    float y;
  };

  struct foo var;
  struct foo* pvar;
  pvar = &var;

  var.x = 5;
  (&var)->y = 14.3;
  printf("%i - %.02f\n", var.x, (&var)->y);
  pvar->x = 6;
  pvar->y = 22.4;
  printf("%i - %.02f\n", pvar->x, pvar->y);
  return 0;
}

Führen Sie dies in vim mit dem folgenden Befehl aus:

:!gcc -o var var.c && ./var

Wird ausgeben:

5 - 14.30
6 - 22.40
1
Rich Vogt
#include<stdio.h>

int main()
{
    struct foo
    {
        int x;
        float y;
    } var1;
    struct foo var;
    struct foo* pvar;

    pvar = &var1;
    /* if pvar = &var; it directly 
       takes values stored in var, and if give  
       new > values like pvar->x = 6; pvar->y = 22.4; 
       it modifies the values of var  
       object..so better to give new reference. */
    var.x = 5;
    (&var)->y = 14.3;
    printf("%i - %.02f\n", var.x, (&var)->y);

    pvar->x = 6;
    pvar->y = 22.4;
    printf("%i - %.02f\n", pvar->x, pvar->y);

    return 0;
}
1
Gopal Rao

Der Operator -> Macht den Code in einigen Situationen lesbarer als der Operator *.

Wie zum Beispiel: (aus dem EDK II-Projekt )

typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_READ)(
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN UINT32                         MediaId,
  IN EFI_LBA                        Lba,
  IN UINTN                          BufferSize,
  OUT VOID                          *Buffer
  );


struct _EFI_BLOCK_IO_PROTOCOL {
  ///
  /// The revision to which the block IO interface adheres. All future
  /// revisions must be backwards compatible. If a future version is not
  /// back wards compatible, it is not the same GUID.
  ///
  UINT64              Revision;
  ///
  /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
  ///
  EFI_BLOCK_IO_MEDIA  *Media;

  EFI_BLOCK_RESET     Reset;
  EFI_BLOCK_READ      ReadBlocks;
  EFI_BLOCK_WRITE     WriteBlocks;
  EFI_BLOCK_FLUSH     FlushBlocks;

};

Die Struktur _EFI_BLOCK_IO_PROTOCOL 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 Member-Funktionszeiger aufzurufen. Sie erhalten folgenden Code:

(*pStruct).ReadBlocks(...arguments...)

Mit dem Operator -> Können Sie jedoch wie folgt schreiben:

pStruct->ReadBlocks(...arguments...).

Welches sieht besser aus?

1
smwikipedia

Dot ist ein Dereferenzierungsoperator, mit dem die Strukturvariable für einen bestimmten Strukturdatensatz verbunden wird. Z.B :

struct student
    {
      int s.no;
      Char name [];
      int age;
    } s1,s2;

main()
    {
      s1.name;
      s2.name;
    }

Auf diese Weise können wir einen Punktoperator verwenden, um auf die Strukturvariable zuzugreifen

0
divya