Search code examples
coperatorsstandardsc99c89

Working of the operators ++ followed by -> in the below example


Consider the code segment given below:

#include <stdio.h>

struct s
{
        int x;
        char c;
};

int main()
{
        struct s x[2]={{1,'a'},{2,'b'}};
        struct s * p;
        p=x;
        int a = p++ -> x; //line of doubt
        printf("%d \n",a);
}

The output of the following code is 1 and it makes it clear that it is actually evaluated as :

int a = ((p++) -> x);

Now my question is, we know that in C , the binary -> operator is having higher precedence than the unary ++ operator. But why is the effect such that the ++ is grouped first and then the ->.

Is it so that being a binary operator it looks for the first operand to its left and it being p the pairing is done as :

int a= *(p++ -> x);

But this includes with p, p++ as a chunk and hence first p++ is considered, but I feel this explanation is a bit vague. Could anyone explain me the proper logic and along with it, could anyone recommend me any book from where I could practice more examples like this.

Edit: Thanks for the answers, actually I have studied C from the texts "The C Programming Language" by Dennis Ritchie et. al and also from "C- The Complete Reference" by Hebert Schildt. In both the texts the operator precedence is as shown:

Operator Precedence Source: "The C Programming Language (2nd Ed.)" by Dennis Ritchie et. al (pg. 53)


Solution

  • The postfix increment operator ++ and the member-access-via-pointer operator -> have the same precedence level, and they group left-to-right. So first p++ is evaluated, then (p++)->x.

    Section 6.5.2p1 of the C standard gives the following syntax declaration for postfix operators:

    postfix-expression:
      primary-expression
      postfix-expression [ expression ]
      postfix-expression ( argument-expression-listopt )
      postfix-expression . identifier
      postfix-expression -> identifier
      postfix-expression ++
      postfix-expression --
      ( type-name ) { initializer-list }
      ( type-name ) { initializer-list , }
    

    Had you used the prefix increment operator, i.e. ++p->x, that has lower precedence than ->, grouping as ++(p->x). So you would end up getting the x member from the object p originally pointed to, then that member would be incremented with the expression evaluating to the incremented member.