user1010101
user1010101

Reputation: 1658

Acessing another structure's member through a pointer

#include<stdio.h>

int main()
{
    struct node
    {
        int data;
        struct node *next;

    };

    struct node n1,n2,n3;
    int i;
    n1.data = 100;
    n2.data = 200;
    n3.data = 300;

    n1.next = &n2;
    n2.next = &n3;

    i = n1.(*next).data;
    printf("%i\n",i);

    printf("%i\n", n2.next->data);

    return 0;
}

My Question is simple. How come i am not able to access n2 node via n1 node when i use this i = n1.(*next).data; I get an error. However if i change it to i=n1.next->data

I thought (*x).y and x->y mean the same thing.

Upvotes: 3

Views: 64

Answers (2)

ericbn
ericbn

Reputation: 10988

You're right, (*x).y and x->y mean the same thing, that's why you should write (*n1.next).data (equivalent to n1.next->data as n1.next is your x).

EDIT: The parenthesis are so due to the evaluation order:

  1. Take n1: n1 (a struct node)
  2. Take member next: (n1).next (a struct node *)
  3. Deference the pointer: *((n1).next) (a struct node)
  4. Take member data: (*((n1).next)).data (an int)

Read what the C11 standard says in the @Christophe answer, and notice how the . operator used in steps 2 and 4 above where used with struct node as first operands (see steps 1 and 3) and member names as seconds operands.

Upvotes: 3

Christophe
Christophe

Reputation: 73456

The syntax requires i = (*n1.next).data;

Why ?

  • C11 standard says "The first operand of the . operator shall have an atomic, qualified, or unqualified structure or union type, and the second operand shall name a member of that type." (§ 6.5.2.3). So n1.*nextand n1.*(next)are not legal, because operator . can be followed only by a member name.

  • n1.next is of type "pointer to struct node", you may dereference it with operator * or ->.

  • Through dereferencing, *n1.next would be a value of type "struct node". Unfortunately, the prefix operator * has a lower precedence than .. This is why *n1.next.data would mean *(n1.next.data) which is of course invalid because n1.next is a pointer, and pointer do not by themselves have members. But (*n1.next) is of type "struct node", so (*n1.next).datacorrectly refers to the member's value.

  • This kind of derefenrcing is quite common, so there is ->. The standard says "The first operand of the -> operator shall have type ‘‘pointer to atomic, qualified, or unqualified structure’’ (...) and the second operand shall name a member of the type pointed to.". This explains the n1.next->data. Fortunately the precedence of . and -> are the same and they evaluate from left to the right, so no parentheses required.

Upvotes: 2

Related Questions