3

假设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;
}

编辑

++i++分解如下:

i++
++(result)

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

*p++ 
++(result).

*p++ 返回一个值 (rvalue) ,而不是指针。那么为什么会有区别呢?

4

2 回答 2

17

后增量的结果是一个右值。你不能修改它。++i++试图修改编译器拒绝的那个右值。

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

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

如果您非常想这样做,您仍然可以通过将指针初始化为指向自身来获得未定义的行为,在这种情况下,两个增量都会尝试修改指针。委员会并没有非常努力地阻止这种情况,可能是因为只有真正的学究才可能会想到这种疯狂的事情。

底线:在这种情况下,编译器主要是试图保护你免受自己的伤害,但如果你足够努力,你仍然可以在脚上开枪。

于 2012-06-17T15:24:20.567 回答
0

++i++分解如下:

i++
++(result)

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

于 2012-06-17T15:24:06.857 回答