对左值与右值的一些个人思考

Posted reborn521615

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对左值与右值的一些个人思考相关的知识,希望对你有一定的参考价值。

今天重温C语言的指针,看的书是《C和指针》,关于左值和右值以及指针表达式的内容看得甚是迷惑与煎熬,怎么会这么难理解,指针表达式又是作为左值又一会作为右值,而且二者有着不一样的含义,为什么当年学习C语言的时候没有遇到这些头疼的问题呢?这就是没有学好C的原因吧。

功夫不负有心人,认真思考,对比总结,竟有些头绪,记录下来吧。以免以后又忘了没有参考。


先谈谈左值与右值的定义吧。

左值就是那些能够出现在赋值符号左边的东西;因此,右值就是那些可以出现在赋值符号右边的东西。

举个例子:

a = b + 25;

a是一个左值,因为它标识了一个可以存储结果值的地点;b + 25是一个右值,因为它指定了一个值。

它们可以互换吗?也就是 b + 25 = a;

原先用作左值的a,此时也可以用作右值,因为每个位置包含一个值。然后 b + 25不能作为左值,因为它并未标识一个特定的位置。因此,这条赋值语句是错误的。

注意,当计算机计算b+25时,它的结果必然保存于机器的某个地方。但是,程序员并没有办法预测该结果会存储于什么地方,也无法保证这个表达式的值下次还会存储于那个地方。其结果是,这个表达式不是一个左值。基于同样的道理,字面值(常数)也都不是左值。


看了上面的总结,是不是有这样的感觉,变量可以作为左值,而表达式不能作为左值?

这是一种错觉,事实情况下并非如此,下面就专门总结这种情况。

第一个例子:

int a[30];
...
a[b+10] = 0;
技术分享图片

[]是下表引用操作符,所以左边实际上是一个表达式,但它却是一个合法的左值,因为它标识了一个特定的位置,这个数组的某个特定的位置。

第二个例子:

int a, *p;
...
p = &a;
*p = 20;
技术分享图片

第一条赋值语句自然不必多说,指向整型变量的指针变量指定了一个特定的位置存放变量a的地址,p可以作为左值;

第二个赋值语句是需要重点分析的:

理解这个表达式作为左值之前,先了解一下*这个操作符。

*这是一个间接访问的操作符。

通过一个指针访问它所指向的地址的过程称为间接访问(indirection)或解引用指针(dereferencing the pointer)。

是不是有点难以理解?

下面直接给出上面的*p作为左值所表达的意义:*p作为左值代表的是指针变量p所指向的地址。

或者说,指针p的值是内存中某个特定位置的地址,*操作符使机器指向那个位置。当它作为左值使用时,这个表达式指定需要进行修改的位置。当它作为右值时,它就是提取当前存储于这个位置的值。

还不是太明白?那。。。

举个实际的例子:

//下面是这些变量的声明
int a = 112, b = -1;
float c = 3.14;
int *d = &a;
float *e = &c;
技术分享图片

d的值是a的位置(&a),假设为100;

当我们对d使用间接访问操作符时,它表示访问内存位置100并察看那里的值。

因此,*d的右值是112;而它的左值表示它指向的那个位置本身,因此是100本身。

我想举了这个实际的例子,大家已经明白了,左值与右值的含义了,不过还是免不了要愤怒。。。(真jr难理解,真jr麻烦!)哎,只能用熟能生巧来安慰自己了。


对于指针表达式,我下篇博文专门介绍一些有深度的内容,可谓是扑朔迷离,但是如果想深入掌握这门语言,还是要下功夫去研究。

本文参考《C和指针》这本书,但是里面画图的做法,我是真的接受不了,让我徒增迷惑。

给出我的csdn博客地址:https://blog.csdn.net/Reborn_Lee

里面有我的更多博文。

以上是关于对左值与右值的一些个人思考的主要内容,如果未能解决你的问题,请参考以下文章

左值与右值的根本区别在于能否获取内存地址,而能否赋值不是区分的依据

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用

左值引用与右值引用