当铸造指针有增量运算符时会发生什么?
例如:
int x[100]; void *p; x[0] = 0x12345678; x[1] = 0xfacecafe; x[3] = 0xdeadbeef; p = x; ((int *) p) ++ ; printf("The value = 0x%08x", *(int*)p);
编译上面的代码会在++运算符的行上生成一个左值所需的错误。
强制转换创建一个int *
类型的临时指针。 您不能增加临时值,因为它不表示存储结果的位置。
在C和C ++标准中, (int *)p
是一个rvalue ,它大致意味着一个只能出现在赋值右侧的表达式。
另一方面, p
是左值 ,这意味着它可以有效地出现在赋值的左侧。 只有左值可以递增。
表达式((int *) p)
处理存储在变量p
中的指针是指向int的指针。 如果要将变量本身视为指向int变量的指针(然后递增它),请使用引用强制转换:
((int *&) p) ++ ;
你可以得到预期的结果
p = (int*)p + 1;
在p
的解除引用指针上使用increment运算符,这是一个左值,也可以:
(*(int**)&p)++;
但是,后者不可移植,因为(void*)p
可能与(int*)p
表示forms不同。
感谢larsmans指向正确的方向。
我冒昧地深入研究这个问题。 因此,为了将来参考,根据C99标准的第6.5.2.4和6.5.4节(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf):
6.5.2.4后缀增量和减量运算符
约束
后缀增量或减量运算符的操作数应具有限定或不合格的实数或指针类型,并且应为可修改的左值
..
..
6.5.4铸造操作员
..
..
[脚注] 89)演员不会产生左值。 因此,对合格类型的强制转换与对该类型的非限定版本的强制转换具有相同的效果。
注意:这仅适用于C. C ++可能以不同方式处理强制转换。
Rvalue表达式((int *) p)
创建int*
类型的临时类型,不能应用operator ++
。
++
需要左值作为其操作数。
正如@FredOverflow提到的左值和rvalues
与赋值几乎没有关系。
数组是左值,但它们无法分配,因为它们是不可修改的。 std::string("Prasoon")
是一个rvalue表达式,它仍然可以出现在赋值运算符的左侧,因为我们可以在临时函数上调用成员函数(在本例中为operator =
)。