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