I have two structs as such, and I'm trying to fully grasp the usage of the arrow operator. Where Item is a struct, which contains a name and grade.
typedef struct ListNodeTag {
    Item item;
    struct ListNodeTag *next;
} ListNode;
typedef struct {
    int size;
    ListNode *first;
} List;
I understand that if I do something like:
List * L;
L = malloc(sizeof(List));
L->first;  // this refers to the first element
But what if I had something like L->first->first? 
Or
ListNode * p,q;
 p->next = q;
Or p->next->next; ?
I get that the arrow notation is deference's and and access member values/variables. But I'm not sure what the last 3 things I've stated are doing exactly? Any help would be much appreciated.
The three examples here:
L->first->first
p->next = q
p->next->next
etc
