该语句的优先级是什么?

In which precedence is this statement evaluated?

++*P--;

这是一道考试题,如果 P 指向数组中任何元素的指针,请解释这条语句的真正作用。

我什至写了一个简单的代码来评估它:

  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]);
    }

但输出结果更让我困惑:

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

看起来它首先取消引用 P,然后增加它的值,然后减少指针 P 的值,但为什么呢?

根据 K&R table 2-1 来自 p53(见下图) ++、-- 和 *(取消引用)从右到左具有相同的优先级和结合性。 所以第一步应该是减少P的值,然后取消引用,然后增加取消引用的值,我错了吗?

你是正确的,优先级是

++(*(P--))

但请注意,减量是一个后缀操作:即使首先更改为 P,表达式的其余部分仍使用 P 的旧值。因此,在您的示例中,首先 P 递减为 array+4,但 P-- 的值为 array+5,因此 array[5] 递增。

你可以想象这个表情

++*P--

以下方式

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

这是一个演示程序

#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 );
}

程序输出为

X
Hello Xorld
Y
Hello Xorld

输出字符串的不同之处在于,表达式++*p-- 更改了字符串本身,而表达式++value; 更改了一个单独的对象。但是道理是一样的。

后缀表达式p--的优先级最高,但其值为p递减前的值

表达式 ++*p-- 中的一元运算符 ++ 和 * 从右到左分组。因此,首先将运算符 * 应用于表达式,然后再应用运算符 ++。