Search code examples
coperator-precedenceside-effectsassociativity

*p++->str : Understanding evaluation of ->


My question is about the following line of code, taken from "The C Programming Language" 2nd Edition:

*p++->str;

The book says that this line of code increments p after accessing whatever str points to.

My understanding is as follows:

  • Precedence and associativity say that the order in which the operators will be evaluated is

    1. ->
    2. ++
    3. *
  • The postfix increment operator ++ yields a value (i.e. value of its operand), and has the side effect of incrementing this operand before the next sequence point (i.e. the following ;)

  • Precedence and associativity describe the order in which operators are evaluated and not the order in which the operands of the operators are evaluated.

My Question:

My question is around the evaluation of the highest precedence operator (->) in this expression. I believe that to evaluate this operator means to evaluate both of the operands, and then apply the operator.

From the perspective of the -> operator, is the left operand p or p++? I understand that both return the same value.

However, if the first option is correct, I would ask "how is it possible for the evaluation of the -> operator to ignore the presence of the ++".

If the second option is correct, I would ask "doesn't the evaluation of -> in this case then require the evaluation of a lower precedence operator ++ here (and the evaluation of ++ completes before that of ->)"?


Solution

  • To understand the expression *p++->str you need to understand how *p++ works, or in general how postfix increment works on pointers.

    In case of *p++, the value at the location p points to is dereferenced before the increment of the pointer p.
    n1570 - §6.5.2.4/2:

    The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it). [...]. The value computation of the result is sequenced before the side effect of updating the stored value of the operand.

    In case of *p++->str, ++ and -> have equal precedence and higher than * operator. This expression will be parenthesised as *((p++)->str) as per the operator precedence and associativity rule.

    One important note here is precedence and associativity has nothing to do with the order of evaluation. So, though ++ has higher precedence it is not guaranteed that p++ will be evaluated first. Which means the expression p++ (in the expression *p++->str) will be evaluated as per the rule quoted above from the standard. (p++)->str will access the str member p points to and then it's value is dereferenced and then the value of p is incremented any time between the last and next sequence point.