Estou lendo um livro chamado "Ensine-se C em 21 dias" (eu já aprendi Java e C #, por isso estou me movendo em um ritmo muito mais rápido). Eu estava lendo o capítulo sobre ponteiros e o operador->
(seta) surgiu sem explicação. Eu acho que é usado para chamar membros e funções (como o equivalente do operador (ponto), mas para ponteiros em vez de membros). Mas não tenho muita certeza..
Posso obter uma explicação e um exemplo de código?
Respostas:
foo->bar
é equivalente a(*foo).bar
, ou seja, obtém o membro chamadobar
da estrutura quefoo
aponta para.fonte
->
operador não seria necessário, pois seria equivalente ao muito mais legívelfoo*.bar
. Toda a confusão de funções de digitação com todos os parênteses extras também teria sido evitada.foo*.bar
e(*foo).bar
ambos seriam equivalentes afoo->bar
? Que talFoo myFoo = *foo; myFoo.bar
?Sim é isso.
É apenas a versão do ponto quando você deseja acessar elementos de uma estrutura / classe que é um ponteiro em vez de uma referência.
É isso aí!
fonte
pvar = &var
?a->b
é apenas uma abreviação de(*a).b
todas as maneiras (o mesmo para funções:a->b()
é abreviação de(*a).b()
).fonte
Eu apenas adicionaria às respostas o "por quê?".
.
é um operador de acesso de membro padrão que tem uma precedência mais alta que o*
operador de ponteiro.Quando você está tentando acessar as partes internas de uma estrutura e a escreveu da mesma forma
*foo.bar
, o compilador pensaria querer um elemento 'bar' de 'foo' (que é um endereço na memória) e, obviamente, esse mero endereço não possui nenhum membro.Portanto, você precisa pedir ao compilador que primeiro desreferencie com
(*foo)
e depois acesse o elemento membro:,(*foo).bar
que é um pouco desajeitado de escrever, para que as pessoas boas tenham uma versão abreviada:foo->bar
que é uma espécie de acesso de membro pelo operador ponteiro.fonte
foo->bar
é apenas uma abreviação de(*foo).bar
. É tudo o que há para isso.fonte
Aqui o para acessar os valores de
i
ej
podemos usar a variávela
e o ponteirop
da seguinte forma:a.i
,(*p).i
ep->i
são todos iguais.Aqui
.
está um "Seletor Direto" e->
um "Seletor Indireto".fonte
Bem, eu tenho que adicionar algo também. Estrutura é um pouco diferente de matriz, porque matriz é um ponteiro e estrutura não. Por isso tem cuidado!
Digamos que eu escreva este pedaço de código inútil:
Aqui o ponteiro
ptr
aponta para o endereço ( ! ) Da variável de estrutura,audi
mas ao lado da estrutura de endereço também há um pedaço de dados ( ! )! O primeiro membro do pedaço de dados tem o mesmo endereço que a própria estrutura e você pode obtê-los apenas desreferenciando um ponteiro como este*ptr
(sem chaves) .Mas se você quer acesso a qualquer outro membro do que o primeiro, você tem que adicionar um designador como
.km
,.kph
,.kg
que são nada mais do que compensa para o endereço base do bloco de dados ...Mas, devido à precedência, você não pode escrever
*ptr.kg
como o operador de acesso.
é avaliado antes do operador de desreferência*
e você obteria o*(ptr.kg)
que não é possível, pois o ponteiro não possui membros! E o compilador sabe disso e, portanto, emitirá um erro, por exemplo:Em vez de utilizar este
(*ptr).kg
e você forçar compilador para 1º cancelar o ponteiro e permitir acesso ao bloco de dados e segundo você adicionar um offset (designador) para escolher o membro.Confira esta imagem que fiz:
Mas se você tivesse membros aninhados, essa sintaxe se tornaria ilegível e, portanto,
->
foi introduzida. Eu acho que a legibilidade é a única razão justificável para usá-lo, poisptr->kg
é muito mais fácil escrever do que isso(*ptr).kg
.Agora, vamos escrever isso de forma diferente, para que você veja a conexão mais claramente.
(*ptr).kg
⟹(*&audi).kg
⟹audi.kg
. Aqui, usei pela primeira vez o fato de queptr
é um "endereço deaudi
", isto é,&audi
e o fato de que os operadores de "referência"&
e "desreferência" se*
cancelam.fonte
Eu tive que fazer uma pequena alteração no programa de Jack para executá-lo. Após declarar o ponteiro de estrutura pvar, aponte-o para o endereço de var. Encontrei esta solução na página 242 de Programação de Stephen Kochan em C.
Execute isso no vim com o seguinte comando:
Saída:
fonte
%
para representar o nome do arquivo atual. Assim:!gcc % && ./a.out
fonte
O
->
operador torna o código mais legível do que o*
operador em algumas situações.Tais como: (citado no projeto EDK II )
A
_EFI_BLOCK_IO_PROTOCOL
estrutura contém 4 membros de ponteiro de função.Suponha que você tenha uma variável
struct _EFI_BLOCK_IO_PROTOCOL * pStruct
e deseje usar o bom e velho*
operador para chamá-lo de ponteiro de função de membro. Você terminará com um código como este:(*pStruct).ReadBlocks(...arguments...)
Mas com o
->
operador, você pode escrever assim:pStruct->ReadBlocks(...arguments...)
.Qual parece melhor?
fonte
saída é 5 5 5
fonte
Dot é um operador de desreferência e usado para conectar a variável de estrutura a um registro específico da estrutura. Por exemplo :
Dessa forma, podemos usar um operador de ponto para acessar a variável de estrutura
fonte
->
. Além disso, esta pergunta já foi respondida por 4,5 anos.