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

时间:2012-06-17 15:18:39

标签: c linux gcc

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

*p++提供与<{1}}对应的整数值

p使整数值增加1

由于按行为,上述两者都产生整数,i++++*p++不应报告相同的错误?但是为什么++i++有效而++*p++给出了编译错误?

++i++

修改

++ 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;
}

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

i++
++(result)

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

2 个答案:

答案 0 :(得分:17)

后增量的结果是右值。您不允许修改它。 ++i++尝试修改编译器拒绝的rvalue。

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

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

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

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

答案 1 :(得分:0)

++i++分解如下:

i++
++(result)

问题:i++返回一个右值,即一个'临时'值,不可递增。这是因为i++在递增之前会返回i