Postfix operators such as the . and -> component selection operators have higher precedence than unary * and &. Thus, *foo->bar will be interpreted as *(foo->bar); the * operator will be applied to the result of foo->bar. Similarly, &bar.foo will be interpreted as &(bar.foo).
So, given the following declarations:
nodeT example;
nodeT *test1 = &example;
nodeT **test2 = &test1;
you would access the ptr member as follows:
example.ptr - The subexpression example has type nodeT; no indirection is required, so we simply use the . component selection operator;
test1->ptr - The subexpression test1 has type nodeT *; there's one level of indirection, so we need to dereference test1 before we can access the ptr member. We do that by either using the -> operator (which implicitly deferences test1), or we can explicitly dereference test1 ourselves and write (*test1).ptr.
(*test2)->ptr - The subexpression test2 has type nodeT **; there are two levels of indirection, so we need to dereference test2 twice before we can access the ptr member. We need to explicitly dereference it once if we want to use the -> operator, or we dereference it twice to use the . operator - (**test2).ptr.
You use the . component selection operator if the left-hand operand is a struct or union type, such as example or (*test1) or (**test2). You use the -> operator if the left-hand operand is a pointer to a struct or union type, such as test1 or (*test2).
Now for the real fun - the ptr member has type nodeT *, so if you want to get the ptr that example.ptr points to, you would write example.ptr->ptr. The subexpression example has type nodeT, so we used the . component selection operator with it. The subexpression example.ptr, however, has type nodeT *, so we'd need to use the -> component selection operator for it. Alternately, we'd have to write (*example.ptr).ptr (remember, *example.ptr is parsed as *(example.ptr)).
Going one step farther, we could write example.ptr->ptr->ptr, or
(*(*example.ptr).ptr).ptr:
example.ptr
example.ptr->ptr
(*example.ptr).ptr
example.ptr->ptr->ptr
(*(*example.ptr).ptr).ptr
Since test is already type nodeT *, it's a little more straightforward:
test1->ptr
(*test1).ptr
test1->ptr->ptr
(*(*test).ptr).ptr
test1->ptr->ptr->ptr
(*(*(*test1).ptr).ptr).ptr
And finally, test2:
(*test2)->ptr
(**test2).ptr
(*test2)->ptr->ptr
(*(**test2).ptr).ptr
(*test2)->ptr->ptr->ptr
(*(*(**test2).ptr).ptr).ptr