在下面的代码中,是*a
右值还是左值?
#include <stdio.h>
void main()
{
int b=2;
int *a=NULL;
a=&b;
*a=3;
printf("%d",*a);
}
正如在http://en.wikipedia.org/wiki/Value_%28computer_science%29中公开的:
左值的内存地址可由正在运行的程序以编程方式访问(例如,通过某些操作符的地址,如 C/C++ 中的“&”),这意味着它们是变量或对某个内存位置的取消引用。右值可以是左值(见下文)或非左值
所以,*a 是一个左值
它是一个左值,可以在右值的上下文中使用。见例子;
int i, j, *p, *q;
p = &i;
q = &j;
*p = 1; // *p is l-value
*q = 2; // *q is l-value
*p = *q // *q is r-value
正如查尔斯贝利在他的评论中指出的那样:- 子表达式*q
仍然是左值,它经历了左值到右值的转换,因为它用于需要右值的上下文中。
现在可能有人会想,为什么*q
还是 l-value?
因为根据 r-value 的定义,r -value 是一个临时值,不会在使用它的表达式之外持续存在。
在这种情况下, is 的值*q
在表达式之外仍然存在*p = *q
。
笔记:
“ * ”操作符——引用/间接操作符——对指针变量进行操作,并返回一个与指针地址处的值等价的左值。
根据 P197 §A5 上的 K&R 第 2 版:
...左值是一个引用对象的表达式...例如,如果
E
是指针类型的表达式,那么*E
是一个左值表达式,引用指向的对象E
。
另外,Scott Meyers 在他的《Effective Modern C++, Introduction - Terminology and Conventions》一书中提出了另一种更简单的方法来确定左值/右值:
确定表达式是否为左值的一个有用的启发式方法是询问您是否可以获取其地址。如果可以,通常是这样。如果你不能,它通常是一个右值。这种启发式的一个很好的特性是它可以帮助您记住表达式的类型与表达式是左值还是右值无关。
因此,当*p
表达式出现在左侧时,它是 a lvalue
,右侧是rvalue
。