为什么++*p ++可以工作而++ i ++没有?

Lun*_*oms 3 c linux gcc

假设p是一个整数指针并且i是一个整数:

*p++给出一个对应的整数值p.

i++给出一个递增1 的整数值

由于按行为,上述两者都产生整数, ++*p++并且++i++不应报告相同的错误?但为什么++*p++工作时 ++i++ 会产生编译错误?

int main()
{
int a[10] = {0};

int *p = (int*)&a;
int i = 0;

// printf("%d", ++i++); -- FAILS error: lvalue required as increment operand   
printf("%d\n", ++*p++ ); // Prints 1
return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑

++ i ++被分解如下:

i++
++(result)
Run Code Online (Sandbox Code Playgroud)

这正是我感到困惑的地方:同样地,我们可以将++*p ++分解为

*p++ 
++(result).
Run Code Online (Sandbox Code Playgroud)

*p ++返回一个值(rvalue),而不是指针.为什么差异呢?

Jer*_*fin 17

后增量的结果是右值.你不能修改它.++i++尝试修改编译器拒绝的rvalue.

p ++产生一个rvalue,但它是指针类型.您不能修改它,但您可以取消引用它.*p++取消引用rvalue.这为您提供了它所指向的值,作为左值.然后,预增量会修改它指向的左值,而不是后增量产生的右值.

编辑:我可能还应该添加一点:即使++i++编译器允许,结果也是未定义的行为,因为它尝试修改i两次而没有插入序列点.在++*p++没有发生这种情况的情况下- 后增量修改指针本身,而预增量修改指针指向的内容(在增加之前).由于我们正在修改两个完全不同的位置,因此结果不是未定义的行为.

如果你想要足够严重,你仍然可以通过初始化指针指向自身来获得未定义的行为,在这种情况下,两个增量都会尝试修改指针.委员会并没有非常努力地防止这种情况,可能是因为只有真正迂腐的人才有可能甚至想到这种疯狂的事情.

底线:在这种情况下,编译器主要是试图保护自己免受伤害,但是如果你努力的话,你仍然可以用脚射击自己.