> Then what is the -> all about?
Because you have a pointer to a struct - a pointer to the memory you got back from malloc.
> Why not use a dot like &Elem.id?
You would use the dot form if you have a variable of that type.
Consider.
Code:
STUDENT s;
STUDENT *ps = malloc(sizeof(*ps));
// read into s
scanf("%d", &s.id);
// read into ps (both are the same)
scanf("%d", &ps->id);
scanf("%d", &(*ps).id); // use the dot form, but only because of all the extra syntax around ps
// you can even use array notation
scanf("%d", &ps[0].id);
The arrow notation is just the least cumbersome of the possible ways of getting from a pointer-to-struct to the actual data element within the struct.