Bueno, tengo que agregar algo también. La estructura es un poco diferente de la matriz porque la matriz es un puntero y la estructura no lo es. ¡Así que ten cuidado!
Digamos que escribo este 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;
}
Aquí puntero ptr apunta a la dirección ( ! ) De la variable de estructura, audipero al lado de la estructura de la dirección también hay una porción de datos ( ! )! El primer miembro de la porción de datos tiene la misma dirección que la estructura misma y puede obtener sus datos solo haciendo referencia a un puntero como este *ptr (sin llaves) .
Pero Si desea acess cualquier otro miembro que el primero, tiene que añada un indicador como .km, .kph, .kgque no es más que compensa a la dirección base del son parte de los datos ...
Pero debido a la precedencia, no puede escribir *ptr.kgya que el operador de acceso .se evalúa antes que el operador de desreferencia *y obtendría lo *(ptr.kg)que no es posible ya que el puntero no tiene miembros. Y el compilador lo sabe y, por lo tanto, emitirá un error, por ejemplo:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
En su lugar, usa esto (*ptr).kgy fuerza al compilador a primero desreferenciar el puntero y habilitar el acceso a la porción de datos y segundo agregar un desplazamiento (designador) para elegir el miembro.
Mira esta imagen que hice:

Pero si hubiera miembros anidados, esta sintaxis se volvería ilegible y, por ->lo tanto, se introdujo. Creo que la legibilidad es la única razón justificable para usarlo, ya que ptr->kges mucho más fácil de escribir que (*ptr).kg.
Ahora permítanos escribir esto de manera diferente para que vea la conexión más claramente. (*ptr).kg⟹ (*&audi).kg⟹ audi.kg. Aquí utilicé por primera vez el hecho de que ptres una "dirección de audi", es decir, &audiy el hecho de que "referencia" & y "desreferencia" * operadores de cancelan entre sí.