Operatore freccia (->) utilizzo in C

Attualmente sto imparando C leggendo un buon libro per principianti chiamato “Teach Yourself C in 21 Days” (ho già imparato Java e C # così mi sto muovendo ad un ritmo molto più veloce). Stavo leggendo il capitolo sui puntatori e l’operatore -> (freccia) si avvicinò senza spiegazione. Penso che sia usato per chiamare membri e funzioni (come l’equivalente dell’operatore. (Punto), ma per puntatori invece di membri). Ma non ne sono del tutto sicuro. Potrei ottenere una spiegazione e un esempio di codice?

foo->bar è equivalente a (*foo).bar , cioè ottiene il membro chiamato bar dalla struttura a cui punta foo .

Sì è quello.

È solo la versione punto quando si desidera accedere agli elementi di una struct / class che è un puntatore anziché un riferimento.

 struct foo { int x; float y; }; struct foo var; struct foo* pvar; var.x = 5; (&var)->y = 14.3; pvar->y = 22.4; (*pvar).x = 6; 

Questo è tutto!

a->b è semplicemente abbreviato per (*a).b in tutti i modi (lo stesso vale per le funzioni: a->b() è l’abbreviazione di (*a).b() ).

foo->bar è solo una scorciatoia per (*foo).bar . Questo è tutto ciò che c’è da fare.

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

Qui per accedere ai valori di j possiamo usare la variabile ae il puntatore p come segue: ai , (*p).i e p->i sono tutti uguali.

Qui è un “Selettore diretto” e -> è un “Selettore indiretto”.

Vorrei solo aggiungere alle risposte il “perché?”.

. è un operatore di accesso membro standard che ha una precedenza più alta dell’operatore * puntatore.

Quando stai provando ad accedere agli interni di una struct e lo hai scritto come *foo.bar il compilatore penserebbe di volere un elemento ‘bar’ di ‘foo’ (che è un indirizzo in memoria) e ovviamente quel mero indirizzo non ha qualsiasi membro.

Quindi è necessario chiedere al compilatore di dereferenziare prima (*foo) e quindi accedere all’elemento membro: (*foo).bar , che è un po ‘goffo da scrivere, quindi i bravi ragazzi hanno escogitato una versione abbreviata: foo->bar che è una sorta di accesso membro da operatore puntatore.

Ho dovuto apportare una piccola modifica al programma di Jack per farlo funzionare. Dopo aver dichiarato il puntatore della struct pvar, puntalo all’indirizzo di var. Ho trovato questa soluzione a pagina 242 di Stephen Kochan’s Programming in C.

 #include  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; } 

Esegui questo in vim con il seguente comando:

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

Produrrà:

 5 - 14.30 6 - 22.40 
 #include 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; } 

L’operatore -> rende il codice più leggibile rispetto all’operatore * in alcune situazioni.

Ad esempio: (citato dal progetto EDK II )

 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; }; 

La struttura _EFI_BLOCK_IO_PROTOCOL contiene 4 membri del puntatore a funzione.

Supponiamo che tu abbia una struct _EFI_BLOCK_IO_PROTOCOL * pStruct variabile struct _EFI_BLOCK_IO_PROTOCOL * pStruct e che tu voglia usare il buon vecchio operatore * per chiamare il suo pointer funzione membro. Finirai con un codice come questo:

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

Ma con l’operatore -> , puoi scrivere così:

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

Quale sembra migliore?

Dot è un operatore di dereferenziazione e utilizzato per connettere la variabile di struttura per un particolare record di struttura. Per esempio :

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

In tal modo possiamo usare un operatore punto per accedere alla variabile struttura

 #include 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); } 

l’output è 5 5 5