0

As per C, PostIncrement(a++) > Dereference(*) > Assignment(=) When I execute this below c snippet,

#include <stdio.h>

int main(){

    int arr[]= {1,2,3};
    int *p = a;

    *p++ = 3;

    for(int i=0;i<3;i++){
        printf("%d ",arr[i]);  
    }

}

Output: 3 2 3

But if we apply order of precedence in this statement,

 *p++ = 3;

The statement will be evaluated in the following order:

  1. p++ will be evaluated
  2. *p will get dereferenced.
  3. then 3 will be assigned to *p using the assignment operator

If we apply the above order, p which is pointing to the start of the array arr, will get incremented first and point to the second element of the array. Then second element's address will get dereferenced and then 3 will be assigned to the second index. So our expected output should be 1 3 3 But the output I got is 3 2 3.

I know that my expected output is not correct. It'll be helpful if you explain the order of evaluation here in this case of the output of the compiler.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Allan
  • 110
  • 9

4 Answers4

3

Precedence only determines the grouping of operators with operands - it does not control the order in which expressions are evaluated. Precedence rules only determine that

*p++ = 3;

should parsed as

*(p++) = 3; // as opposed to (*p)++ = 3 or *(p++ = 3)

not that operations be executed in a specific order.

The ++ and –– operators have a result and a side effect. The result of postfix ++ is the current value of the operand; the side effect is to increment the operand. Your expression is logically equivalent to

tmp = p;
*tmp = 3;
p = p + 1;

with the caveat that the assignment to *tmp and the update of ptr can happen in any order, and they can even be interleaved or executed in parallel.

John Bode
  • 119,563
  • 19
  • 122
  • 198
2

The result of a post-increment expression is the value of the operand before it is incremented. Thus, even though the ++ in *p++ does, indeed, have higher precedence than the *, the latter is applied to the result of the p++ expression which is, as just mentioned, the initial value of p.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • so if it's ++p then (++p) will first increment and then give the result. If it's (p++) then p++ will first give p and then increment it right? – Allan Apr 18 '21 at 12:09
  • @Allan Effectively, yes. However, there is no actual requirement of the timing of operations; just that the value of the `p++` expression will be what `p` was before the `++`. – Adrian Mole Apr 18 '21 at 12:10
  • Nice. Thanks for that. – Allan Apr 18 '21 at 12:12
  • int a[]= {1,2,3}; int *p = a; int k = *(p++) * (*(p++)); Can you help me with the order of evaluation here? the output is 2. I want to know whether it's done left to right or right to left – Allan Apr 18 '21 at 12:17
  • 1
    @Allan This code snippet has undefined behavior. – Vlad from Moscow Apr 18 '21 at 12:28
  • 1
    @Allan On the use of multiple, unsequenced `++` operations, see: [Why are these constructs using pre and post-increment undefined behavior?](https://stackoverflow.com/q/949433/10871073) – Adrian Mole Apr 18 '21 at 12:37
2

According to the C Standard (6.5.2.4 Postfix increment and decrement operators)

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.

Thus in this statement

 *p++ = 3;

the expression p++ returns the current value of the pointer p that is a pointer that points to the first element of the array. It is this pointer to the first element of the array that is dereferenced.

So this statement

 *p++ = 3;

is not equivalent to the statements

p++;
*p = 3;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

"The statement will be evaluated in the following order:

p++ will be evaluated *p will get dereferenced. then 3 will be assigned to *p using the assignment operator"

Post Increments operator doesn't work like that. You can assume like this for better understanding.

  • When p++ gets evaluated, first, its present value is stored at a temporary location then the increment takes places.
  • All remaining operations are performed on the value stored in temporary location.
  • For subsequent statements incremented value is used.
EMS
  • 104
  • 1
  • 6
  • Note that there is no specification in the C Standard about the actual order of evaluation. Just that the result of the post-increment expression will be the (original) value of its operand. – Adrian Mole Apr 18 '21 at 12:11
  • @AdrianMole, which is why I wrote "You can assume" – EMS Apr 18 '21 at 12:16