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:
#include <stdio.h>
typedef struct{
int km;
int kph;
int kg;
} car;
int main(void){
car audi = {12000, 230, 760};
car *ptr = &audi;
}
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:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
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, pois ptr->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 que ptr
é um "endereço de audi
", isto é, &audi
e o fato de que os operadores de "referência"&
e "desreferência" se *
cancelam.