0
++*P--;

That is a question from an exam, if P a pointer to any element in an array, explain what this statement really does.

I even wrote a simple code to evaluate it:

  int i;
    int* array = calloc(10, sizeof(int));
    for (i = 0; i < 10; i++) {
        array[i] = i;
        printf("%d,", array[i]);
    }
    int* P = array + 5;
    printf("\n %p", P);
    printf("\n %d", *P);

    ++*P--;
    printf("\n %p", P);
    printf("\n %d \n", *P);
    for (i = 0; i < 10; i++) {
        printf("%d,", array[i]);
    }

But the output confuses me even more:

0,1,2,3,4,5,6,7,8,9,
 0x100105534
 5
 0x100105530
 4 
0,1,2,3,4,6,6,7,8,9,

It looks like it first dereferences P, then increases its value and then decreases value of pointer P, but why?

According to K&R table 2-1 from p53 (see the picture below) ++, --, and * (dereference) has the same precedence and associativity from right to left. So first step should be decreasing value of P, then dereference and then increasing dereferenced value, am I wrong?

enter image description here

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Anatoly
  • 5,056
  • 9
  • 62
  • 136
  • Precedence and evaluation have nothing to do with one another. Precendence determines the meaning of a sequence of source code (it's a part of the parsing rules). Evaluation is about establishing the value of an expression. You need to know first what something means before you can compute its value. – Kerrek SB Jul 15 '15 at 22:22

2 Answers2

3

You are correct that the precedence is

++(*(P--))

But note that the decrement is a postfix operation: even though the change to P happens first, the rest of the expression uses the old value of P. So in your example, first P is decremented to array+4, but the value of P-- is array+5, so array[5] gets incremented.

aschepler
  • 70,891
  • 9
  • 107
  • 161
2

You can imagine this expression

++*P--

the following way

int *tmp = p;
--p;
int value = *tmp;
++value;

Here is a demonstrative program

#include <stdio.h>

int main( void )
{
    char s[] = "Hello World";
    char *p = s + 6;

    std::printf( "%c\n", ++*p-- );
    std::printf( "%s\n", s );

    p = s + 6;
    char *tmp = p--;
    char value = *tmp;
    ++value;

    std::printf( "%c\n", value );
    std::printf( "%s\n", s );
}

The program output is

X
Hello Xorld
Y
Hello Xorld

The difference in the outputting the string is that expression ++*p-- changes the string itself but expression ++value; changes a separate object. But the logic is similar.

Postfix expression p-- has the highest priority but its value is the value of p before decreasing.

Unary operators ++ and * in expression ++*p-- group right to left. So at first operator * is applied to the expression and after that operator ++ is applied.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335