Reputation: 4853
EDIT - updated with 2-star pointer for more relevancy
Say I had a two-star pointer to a structure that also contained a pointer.
typedef struct{
nodeT *ptr;
}nodeT;
nodeT example;
nodeT *test1 = &example;
nodeT *test = &test1;
If I wanted the address of the pointer in the structure, what would the syntax be? I tried this:
&(*test->ptr)
Where it was a thought that the parethesis would reduce to the actual pointer, after which the & operator is used to return the address.
Rather, I found this to be the correct syntax by trial and error:
&(*test)->ptr;
Further, I was confused why the below syntax does not work to even dereference the test
pointer to the structure pointer:
*test->ptr;
It was my experience that without the parenthesis around *test
the compiler returned a statement informing me I was attempting to access something not a part of a structure or union.
It must have something to do with the priority assigned to the various format elements that I am not fully aware.
Any ideas?
Upvotes: 2
Views: 524
Reputation: 2589
Since test
is a pointer, you can't access it's fields using the .
operator, you have to first dereference the pointer to get the struct directly:
*test
After that, you can access the field with the .
operator:
(*test).ptr
The ->
operator is a shortcut to dereferencing the struct pointer:
test->ptr
That will get the ptr variable, just like the last expression. If what you want it the address pointed by ptr, then you are set.
If you want the address of the ptr variable, then you'll need to get its address by using the &
:
(&test)->ptr
or
&(*test).ptr
Upvotes: 1
Reputation: 123558
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
Upvotes: 3
Reputation: 754590
Given:
nodeT n0 = { 0 };
nodeT n1 = { &n0 };
nodeT *test = &n1;
You can use:
test // Pointer to n1
&test // Pointer to test itself
test->ptr // Pointer to n0
(*test).ptr // Same as test->ptr
&test->ptr // Pointer to the element of n1 (same as n1 because of the struct def'n
test->ptr->ptr // Pointer to null
Etc.
For example:
#include <inttypes.h>
#include <stdio.h>
typedef struct nodeT nodeT;
struct nodeT { nodeT *ptr; };
static void print_addr(char * const tag, void *addr)
{
printf("%-15s = %p\n", tag, addr);
}
int main(void)
{
nodeT n0 = { 0 };
nodeT n1 = { &n0 };
nodeT *test = &n1;
print_addr("test", test);
print_addr("&test", &test);
print_addr("test->ptr", test->ptr);
print_addr("(*test).ptr", (*test).ptr);
print_addr("&test->ptr", &test->ptr);
print_addr("test->ptr->ptr", test->ptr->ptr);
return 0;
}
Example output:
test = 0x7fff58829b10
&test = 0x7fff58829b20
test->ptr = 0x7fff58829b00
(*test).ptr = 0x7fff58829b00
&test->ptr = 0x7fff58829b10
test->ptr->ptr = 0x0
Upvotes: 1
Reputation: 24895
test->ptr
is the same that (*test).ptr
So, I think you want &(test->ptr)
(I am not sure of which operator has more priority).
Upvotes: 4