Sagrian
Sagrian

Reputation: 1048

order of evaluation for multiple increment operator on pointer

Having trouble understanding, How following statement would be evaluated :

++*++ptr and *ptr++++

As per my understanding first would give me lValue required because after * is applied it would give value which cannot be used for ++ operator. But, the result is opposite. Please explain.

Second statement gives me error : batch3.c:6:21: error: lvalue required as increment operand printf("%d", *ptr++++);

Upvotes: 2

Views: 739

Answers (3)

John Bode
John Bode

Reputation: 123578

First, some standardese:

6.5.2.4 Postfix increment and decrement operators

Constraints

1 The operand of the postfix increment or decrement operator shall have atomic, qualified, or unqualified real or pointer type, and shall be a modifiable lvalue.

Semantics

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). See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The value computation of the result is sequenced before the side effect of updating the stored value of the operand. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. Postfix ++ on an object with atomic type is a read-modify-write operation with memory_order_seq_cst memory order semantics.98)
...
6.5.16 Assignment operators
...
3 An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.

Emphasis mine.

The upshot of that wall of text is that the results of the expressions ptr++ and ++ptr are not lvalues. However, both expressions result in pointer values, so they may be the operands of the unary * operator, and the results of *ptr++ and *++ptr may be lvalues.

This is why ++*++ptr works; you're incrementing the result of *++ptr, which may be an lvalue. However, *ptr++++ is parsed as *(((ptr)++)++) (postfix ++ has higher precedence than unary *); the result of ptr++ is the operand to the second ++, but since the result of ptr++ is not an lvalue, the compiler complains. If you had written it as (*ptr++)++, then the expression would be valid.

In short:

++*++ptr     - valid, equivalent to ++(*ptr++)
*++++ptr     - invalid, equivalent to *(++(++ptr)), result of ++ptr is not an lvalue
++++*ptr     - invalid, equivalent to ++(++(*ptr)), result of ++*ptr is not an lvalue
*ptr++++     - invalid, equivalent to *((ptr++)++), result pf ptr++ is not an lvalue
(*ptr)++++   - invalid, equivalent to ((*ptr)++)++, result of (*ptr)++ is not an lvalue
(*ptr++)++   - valid

Upvotes: 2

Grzegorz Szpetkowski
Grzegorz Szpetkowski

Reputation: 37954

Considering that these two expressions are separate (note that and is defined <iso646.h>) here what happens:

First one ++*++ptr is equivalent to ++(*(++ptr)), as both prefix ++ and unary * have the same precedence and assiociativity is from right to left for both of them. See following example as an illustration:

#include <stdio.h>

int main(void)
{
    int a[] = {1, 2};
    int *ptr = a;

    ++(*(++ptr));

    printf("%d\n", a[0]);
    printf("%d\n", a[1]);

    return 0;
}

Result:

1
3

The latter expression is not compilable, as ptr++ subexpression is not a modifiable lvalue. Note that postix ++ has higher precedence, that * (indirection operator) and its associativity is from left to right.

Upvotes: 1

Gopi
Gopi

Reputation: 19874

++ operator has higher precedence over *

So the pointer will be incremented first and then dereferenced.

*p++

First

p++

Then *p++

For ++ there has to be a value which needs to be incremented. But the below expression doesn't provide the lvalue for the ++ . p++ is not a modifiable lvalue.

*ptr++++;

Upvotes: 1

Related Questions