Uso do operador de seta (->) em C

Atualmente estou aprendendo C lendo um bom livro para iniciantes chamado “Teach Yourself C in 21 Days” (eu já aprendi Java e C #, então estou me movendo em um ritmo muito mais rápido). Eu estava lendo o capítulo sobre pointers e o operador -> (seta) apareceu sem explicação. Eu acho que ele é usado para chamar membros e funções (como o equivalente do operador. (Ponto), mas para pointers em vez de membros). Mas não tenho certeza absoluta. Por favor, posso obter uma explicação e uma amostra de código?

foo->bar é equivalente a (*foo).bar , isto é, obtém o membro chamado bar da estrutura que foo aponta para.

Sim é isso.

É apenas a versão ponto quando você deseja acessar elementos de uma struct / class que é um ponteiro em vez de uma referência.

 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; 

É isso aí!

a->b é curto para (*a).b em todos os sentidos (o mesmo para funções: a->b() é curto para (*a).b() ).

foo->bar é apenas uma abreviação para (*foo).bar . Isso é tudo que existe para isso.

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

Aqui, para acessar os valores de i e j , podemos usar a variável a e o ponteiro p seguinte forma: ai , (*p).i e p->i são todos iguais.

Aqui é um “seletor direto” e -> é um “seletor indireto”.

Eu adicionaria as respostas “por quê?”

. é um operador de access de membro padrão que tem uma precedência maior que o operador * pointer.

Quando você está tentando acessar internals de uma estrutura e você escreveu como *foo.bar então o compilador pensaria querer um elemento ‘bar’ de ‘foo’ (que é um endereço na memory) e obviamente que o mero endereço não tem quaisquer membros.

Assim, você precisa pedir ao compilador que primeiro desrefere whith (*foo) e, em seguida, acesse o elemento membro: (*foo).bar , que é um pouco desajeitado para escrever, então o pessoal bom criou uma versão abreviada: foo->bar que é uma espécie de access de membro pelo operador de ponteiro.

Eu tive que fazer uma pequena alteração no programa de Jack para fazê-lo funcionar. Depois de declarar o struct pointer pvar, aponte para o endereço de var. Eu encontrei esta solução na página 242 da programação de Stephen Kochan em 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; } 

Execute isto no vim com o seguinte comando:

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

Saída:

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

O operador -> torna o código mais legível que o operador * em algumas situações.

Tais como: (citado do projeto 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; }; 

A estrutura _EFI_BLOCK_IO_PROTOCOL contém 4 membros de ponteiro de function.

Suponha que você tenha uma variável struct _EFI_BLOCK_IO_PROTOCOL * pStruct e queira usar o bom e velho operador * para chamar seu ponteiro de function de membro. Você vai acabar com o código como este:

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

Mas com o operador -> , você pode escrever assim:

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

Qual parece melhor?

Dot é um operador de remoção de referência e usado para conectar a variável de estrutura a um registro específico de estrutura. Por exemplo :

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

De tal forma, podemos usar um operador de ponto para acessar a variável de estrutura

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

a saída é 5 5 5