4

Here is another naïve question from a C newbie: on this page, https://en.cppreference.com/w/c/language/operator_precedence, the precedence of the postfix increment is listed to be higher than that of pointer dereference. So I was expecting in the following code that the pointer is incremented first (pointing at 10) and then dereferenced.

#include <stdio.h>

int main()
{
  int a[] = {3, 10, 200};
  int *p = a;
  printf("%d", *p++);
  return 0;
}

However this code outputs still the first array item (3). What am I missing by the concept?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Student
  • 708
  • 4
  • 11
  • 1
    If it is post-increment it cannot be incremented first. That would be pre-increment. The post-increment happens at some unspecified moment between accessing the variable, and the next sequence point. – Weather Vane Aug 18 '21 at 08:44
  • 1
    Partially related: [Why does a=(b++) have the same behavior as a=b++?](https://stackoverflow.com/questions/31087537/why-does-a-b-have-the-same-behavior-as-a-b) – Steve Summit Aug 18 '21 at 14:18

4 Answers4

5

Precedence is placing of parenthesis.

The expression *p++ can be parenthesized as

(*p)++ // incorrect precedence
*(p++) // correct precedence

Note that the value of p++ is the value of p before any change, so the net effect of the correct precedence is the same as *p without ant reflection over the side-effect ++. The change to p itself does not alter the result of *(p++).

pmg
  • 106,608
  • 13
  • 126
  • 198
  • I was more interested in the listing of the link I sent, specifically what does it mean that the postfix ++ has a higher precedence, or better asked in which situations? – Student Aug 18 '21 at 08:49
  • Precedence relates to placing of parenthesis, not to order of operations. The expression `*(p++)` has 2 operations: getting a value from a pointer and incrementing the pointer ... the order of these operations is unspecified but does not change the final result whatever the compiler chooses. – pmg Aug 18 '21 at 08:51
  • Means writing `*p++` or `*(p++)` doesn't make any difference? – Student Aug 18 '21 at 08:54
  • Right. `*p++` "relies on" precedence, `*(p++)` is doing the exact same thing with an extra (redundant, but maybe useful) pair of parenthesis. – pmg Aug 18 '21 at 08:55
  • 1
    Rather, it has 3 operations: getting the value from p, incrementing p and de-referencing the value obtained in the first operation. The operation "getting the value from p" is specified to be sequenced before the other two. But incrementing p and de-referencing the value aren't sequenced in relation to each other (and the order doesn't affect the result). – Lundin Aug 18 '21 at 08:56
4

As you have correctly assumed, the expression *p++ is evaluated as *(p++); that is, the ++ operator has higher precedence than the * operator.

However, the value of the expression, p++, is just the value of p (i.e. its value before the increment). A side-effect of the operation is that the value of p is incremented after its value has been acquired.

From this Draft C11 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). … 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. …

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • This quote doesn't explain anything meaningful though. The actually relevant part is left out from your quote. "The value computation of the result is sequenced before the side effect of updating the stored value of the operand." – Lundin Aug 18 '21 at 08:58
3

Operator precedence specifies how an expression is parsed. Since postfix ++ has higher precedence than *, the expression is equivalent to *(p++). Rather than (*p)++ which would have given it a completely different meaning.

But just because this forces p++ to be evaluated first, it doesn't affect the characteristic of the ++ operator. The C language specifies this operator to behave as (from C17 6.5.2.4/2):

"The value computation of the result is sequenced before the side effect of updating the stored value of the operand."

This means that p++ always gives the value of p before ++ is applied. In this case p is a pointer, so the value will be the address it pointed at prior this expression. So the code is completely equivalent to this:

int* tmp = p;
p++;
printf("%d", *tmp);
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Precedence controls which operators are grouped with which operands. Postfix ++ having higher precedence than unary * simply means that *p++ is parsed as *(p++) instead of (*p)++.

*(p++) means you are dereferencing the result of p++. The result of p++ is the current value of p. As a side effect p is incremented. It is logically equivalent to

tmp = p;
printf( "%d\n", *tmp );
p = p + 1;

where the printf call and the update to p can happen in any order, even simultaneously (interleaved or in parallel).

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