【C语言深入】细聊C语言中的“左值”和“右值”

这篇具有很好参考价值的文章主要介绍了【C语言深入】细聊C语言中的“左值”和“右值”。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、C语言中的“左值”和“右值”

1、左值

左值就是那些可以出现在赋值符号左边的东西,它标识了一个可以存储结果值的地点。
程序在编译时,编译器会为每个变量分配一个地址(左值),这个地址在编译是即可知。
也就是说,左值在编译时即可知,左值标志存储结果的一个地方,也可以理解为左值就是一块空间。

2、右值

右值就是那些可以出现在赋值符号右边的东西,它必须具有一个特定的值。
与左值相反,变量中存储的那个值(右值),只有在运行时才可知,且只有要用到变量中存储的值时,编译器才会发出指令从指定的地址读入变量的值,并将它存于寄存器中。
也就是说,右值就是一个数字或一个字面值或一个常量,它并不标识任何位置。

左值和右值的区别

对于大多数表达式(几乎全部),他们都有右值的属性,因为每个变量所标识的地址空间中都会存储一个值,只要表达式计算不出错,都能计算出一个特定的值。
但并不是所有的表达式都具有左值的属性,例如现在有以下变量和表达式:

int a = 3;
int b = 5;
a = b + 25; 
b + 25 = a;

其中表达式a是一个左值,因为它标识一个特定的位置(a变量的地址),但b + 25就不是一个左值,因为它并未标识一个特定的位置。
当然,计算机在计算b + 25的时候,一定是把它的结果存储与内存的某个位置,但这对于程序员来说是无法预测的,程序员也不能保证这个表达式的值下一次还会存储在同一个地方。
故b + 25不是一个左值。

二、与“位置”相关的操作符

1、取地址操作符&

之前已经就取地址操作符的功能论述过此操作符了,但今天是就此操作符产生的是左值还是右值再讨论一番。
我们都知道取地址操作符&的作用是取出一个变量的地址,但是它产生的结果是个左值还是右值呢?
可能我在上面就已经说清楚了,它产生的结果是一个右值,因为如果对一个变量取地址,这个地址应该存储在内存的什么位置呢,这是为清晰定义的,用图来解释就是如下图:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio

&ch就相当于取出了ch的地址,存储在了内存中的某个位置,但这个位置是未知的。
而且如今的编译器都是动态的分配内存空间的,也就是说程序这次执行和下一次执行时,同一个变量的地址是不同的。
所以,取地址操作符产生的结果是一个右值,也可以说是一个地址常量或指针常量。

2、间接访问操作符*

积案解引用操作符*是作用域指针的,它的功能通过指针访问指针中存储的地址,它产生的结果是一个左值,但它所产生的这个“左值”既可以作为左值使用也可以作为右值使用。
这可能有点儿难以理解,其实也并没这么难,只要记住下面这个结论,那么对于一些复杂的指针运算就能清楚的理解了:

在类型相同的情况下,对指针解引用,代表指针所指向的目标。

我们现在看一个实例:

int a = 0;
int *p = &a;

上面的结论的意思就是,对于*p我们可以直接认为它等价于a,置于用的是a的左值还是右值,那要视情况而定。
也可以总结为:

对p解引用,是取出p中的地址,访问改地址指向的内存单元的空间或者内容(其实根据指针变量访问,本质是一种间接寻址的方式)。

三、指针表达式作为左值和右值

说到地址和位置,就一定避不开指针,有些人对于一些复杂的指针表达式,很难分清它到底表达的意义是什么?(其结果是左值还是右值?)。
今天我就给大家好好的来分析一下那些令人眼花缭乱的指针表达式到底是个什么东西:

1、当指针单独出现在表达式中时

当指针单独出现在表达式中时候,它既可以作为左值也可以作为右值使用,作为左值时它的结果表示指针所在的存储位置,右值就是指针的值(也就是一个地址常量)。
假设现在有一个字符型变量和字符型指针:

char c = 'a';
char *p = &c;

用画图的方式来理解,就如下图:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio
上图中黑色的方框表示的是位置(空间),黑的的椭圆表示的是内容。
所以上图所表达的意思是:p作为左值时所表示的就是变量p所在的位置,作为右值的时候表示的是变量p中的内容(c的地址)

2、当对指针解引用时

对指针解引用时,它产生的结果也是既可以作为左值也可以作为右值,作为左值是它表示的是指针中存储的地址的那块空间,作为右值时它表示的是指针中存储的地址的那块空间中的内容。
用图解的方式表示,就如下图:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio
其实这里就已经可以用到我们上面所说的结论了,就是*p等价于c,只不过用的是c的左值还是右值要看具体情况。

3、当对指针取地址时

当对指针取地址时,它是一个合法的右值,但却不是一个合法的左值,原因我想上面已经说过了。
当它作为一个右值时,它表示的是变量cp的地址(是个地址常量),但这个地址的存储位置是未清晰定义的,所以它不是一个合法的左值。
用图来解释的话,就如下图:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio

4、当对指针加减整数时

当对指针加减整数时它的右值表示的是它存储的地址跳过一个类型长度后的地址(是个是个地址常量),但它不是一个合法的左值,原因我想应该很清晰了,因为保存这个地址常量的空间并未被清晰定义。
用图来解释,就如下图:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio
这里需要注意的是任何变量在进行计算的时候,用的都是它的右值,所以表达时所产生的结果都是一个常量(也可以说是一个副本),所以对于指针的自加或自减(前置和后置都一样),其实分析方式都和上图一样,所以都是合法的右值,而不是一个合法的左值。

5、当对“指针加减整数”解引用时

当对“指针加减整数”解引用时,它的结果既是一个合法的右值也是一个合法的左值,没错!你没有听错,它是一个合法的左值,虽然“指针加减整数”本身不是一个合法的左值,但加上了解引用操作符之后就能将它变成一个合法的左值。间接引用是少数几个其结果为做值的操作符之一。
当它作为右值时,表示的是指针中存放的地址跳过一个类型长度后的地址中的内容,当它作为左值时,表示的是指针中存放的地址跳过一个类型长度后的地址的空间。
用文字描述实在太费劲,还是看图吧:
c语言中的左值和右值,C语言之路,c语言,c++,数据结构,开发语言,visual studio
这里在计算时其实是先拿出p中保存的地址(常量)与1相加,从而产生了一个“副本”(如图中的虚线椭圆所示),在通过这个“副本”的值找到对应地址的空间或值。
但千万要注意的是,虽然*(p + 1)是一个合法的左值,但并不代表它是一个合法的访问方式,因为p + 1的位置是并没又被分配的,所以对它的访问是非法的。
既然我们已经懂得了这个,那我们理解 ++p和p++也就水到渠成了,他们都是合法的左值和右值。只不过*++p这种访问方式是非法的。文章来源地址https://www.toymoban.com/news/detail-626848.html

到了这里,关于【C语言深入】细聊C语言中的“左值”和“右值”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DevOps中的左移和右移

        一段时间以来,随着DevSecOps、DevTestOps的出现,表明DevOps软件开发方法已完全成熟并进化到了新的阶段,但究其根本,仍是通过频繁发布小型构建来加快产品的生产速度和上线速度。作为渐进交付的连续周期的一部分,DevOps开发团队采用了左移和右移的原则,以确保在这

    2024年02月11日
    浏览(41)
  • [开发语言][c++]:左值、右值、左值引用、右值引用和std::move()

    写在前面: 如果你也被 左值、右值、左值引用、右值引用和std::move 搞得焦头烂额,相关概念和理解不够深入,或者认识模棱两可,那么这篇文章将非常的适合你,耐心阅读,相信一定会有所收获~~ 左值: 可以取地址、位于等号左边 – 表达式结束后依然存在的持久对象

    2024年02月02日
    浏览(62)
  • 详解 C++ 左值、右值、左值引用以及右值引用

    左值是一个表示数据的表达式,比如: 变量名、解引用的指针变量 。一般地,我们可以 获取它的地址 和 对它赋值 ,但被 const 修饰后的左值,不能给它赋值,但是仍然可以取它的地址。 总体而言,可以取地址的对象就是左值。 右值也是一个表示数据的表达式,比如: 字面

    2023年04月08日
    浏览(50)
  • MordernC++之左值(引用)与右值(引用)

    C++中左值与右值的概念是从C中继承而来,一种简单的定义是 左值能够出现再表达式的左边或者右边,而右值只能出现在表达式的右边 。 另一种区分左值和右值的方法是: 有名字、能取地址的值是左值,没有名字、不能取地址的值是右值 。比如上述语句中a,b, c是变量可以

    2023年04月09日
    浏览(41)
  • C++左值右值完美转发转移

    英文含义: 左值(Lvalue) : Locator value ,意味着它指向一个具体的内存位置。 右值(Rvalue) : Read value ,指的是可以读取的数据,但不一定指向一个固定的内存位置。 定义 左值 :指的是一个持久的内存地址。左值可以出现在赋值操作的左侧或右侧。例如,变量、数组的元

    2024年03月10日
    浏览(54)
  • C++ 学习系列 1 -- 左值、右值与万能引用

    简单的说,左值可以放在等号的左边,右值可以放在等号的右边。 左值可以取地址,右值不能取地址。 1.1 左值举例: 变量、函数或数据成员 返回左值引用的表达式 如 ++x、x = 1、cout \\\' \\\'  int x = 0 1.2 右值举例: 返回非引用类型的表达式 如 x++、x + 1 除字符串字面量之外的字面

    2024年02月14日
    浏览(43)
  • 初识C++之左值引用与右值引用

    目录 一、左值引用与右值引用 1. 左值和右值的概念 1.1 左值 1.2 右值  1.3 左值与右值的区分 2. 左值引用与右值引用 2.1 左值引用与右值引用的使用方法 2.2 左值引用的可引用范围 2.3 右值引用的可引用范围 3. 右值引用的作用 3.1 减少传值返回的拷贝 3.2 插入时的右值引用 4

    2023年04月26日
    浏览(40)
  • 左值引用、右值引用,std::move() 的汇编解释

    1:左值引用 引用其实还是指针,但回避了指针这个名字。由编译器完成从地址中取值。以vs2019反汇编: 如图,指针和引用的汇编代码完全一样。但引用在高级语言层面更友好,对人脑。比如可以少写一个 * 号和 - 。 ,以下是指针和引用的使用: 以上就是左值引用,引用的

    2024年02月04日
    浏览(39)
  • C++面试八股文:什么是左值,什么是右值?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第16面: 面试官:什么是左值,什么是右值? 二师兄:简单来说,左值就是可以使用 符号取地址的值,而右值一般不可以使用 符号取地址。 二师兄:一般左值存在内存中,而右值存在寄存器中。 二师兄:严格意义上分,右值

    2024年02月09日
    浏览(41)
  • C++右值引用(左值表达式、右值表达式)(移动语义、完美转发(右值引用+std::forward))(有问题悬而未决)

    在 C++ 中,表达式可以分为左值表达式和右值表达式。左值表达式指的是可以出现在赋值语句左边的表达式,例如变量、数组元素、结构体成员等;右值表达式指的是不能出现在赋值语句左边的表达式,例如常量、临时对象、函数返回值等。 右值是指将要被销毁的临时对象或

    2024年02月04日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包