解引用指针是有效的左值吗?

25

假设定义如下:

int i  = 10;
int *p = &i;

为什么 *p 在这里是一个有效的左值:

*p+=10; 

*p不应该评估为存储在&i处的int值,即10,因此会生成“Not an lvalue”错误吗?


1
我不知道为什么你被踩了。我认为这是一个很好的问题。 - SiegeX
2
我一直认为 *pi 的同义词,从未遇到过任何困惑。 - Kevin
4
当作为右值使用时,*p 会被评估为存储在 &i 上的整数值。但是当作为左值使用时,它与左值 i 相同。 - aschepler
2
*p 总是表示“由 p 指向的位置的内容”。将 *p 解释为左值和右值之间的区别在于,当 *p 作为左值出现时,人们理解的意图是将数据 存储到 p 指向的位置中,而当 *p 作为右值使用时,人们理解的意图是 检索 p 指向的内存位置的内容。 - Bob Jarvis - Слава Україні
@Kevin - 我在脑海中将 *p 解读为“指针 p 的对象”。可能有点冗长,但是在我的思维中,*p += 10 被翻译为“指针 p 的对象增加了 10”。 - Bob Jarvis - Слава Україні
从哲学的角度来看,如果 *p 总是一个 r-value,那么指针的意义何在?它们将变得有效地只读... - Jens
5个回答

15
一个左值表达式是指可以被操作的存储区域。

*p是这样一个表达式,它引用了一块存储区域。这与10+=10;不同,因为10不像变量一样引用存储区域。


2
10是一个表达式。它只不过不是一个左值。 - Antti Haapala -- Слава Україні

3

C11 6.5.3.2p4

语义

...

  1. 一元运算符*表示间接引用。如果操作数指向一个函数,则结果是一个函数指示符;如果操作数指向一个对象,则结果是一个左值,指明该对象。如果操作数具有“指向类型”,则结果具有“类型”。如果将无效值分配给指针,则一元运算符*的行为未定义。

也就是说:

int i  = 10;
int *p = &i;
*p 的结果是一个 lvalue,它指代对象 i。因此,*p += 10 是有效的,因为它是一个 lvalue。
现在,如果 lvalue 被用在需要对象本身的上下文中,它将被转换为指定对象中存储的值。这被称为 lvalue 转换,其结果当然不再是 lvalue(参见 C11 6.3.2.1p2)。

2

我相信您对p的定义感到困惑。实际上,p是一个类型为指向整数的指针的变量,并且其值被初始化为i的地址。

然而,*p也是一个有效的lvalue——一个有效的表达式,指向存储位置。


2

简单来说,指针指向一个对象(在一般的非面向对象的意义上),而不是该对象的内容。因此,是的,解引用指针是有效的左值。

从非常低层次来看,指针仅仅是一个内存地址,解引用指针就是该地址处的内存。


2

应该不会出现“Not an lvalue”错误,因为*p应该评估为存储在&i中的int值,即10。

简单来说:

*表示“地址上的值”。

*p表示“地址是p的值所指向的位置上的值”。

*p = 10;表示“将10设置为地址是p的值所指向的位置上的值”。

lvalue是指存储在内存中某个位置上的对象的表达式。 *p也是一个表达式,它指的是存储在位置p上的对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接