重要的内容要重复强调: C语言的术语Ivalue指用于识别或定位一个存储位置的标识符。( 注意:左值同时还必须是可改变的)
其实rvalue的发明完全是为了搭配lvalue , rvalue你可以理解为readable value ,即任何可读取的值都被认为是右值(非左值).
原文地址
https://www.dotcpp.com/wp/692.html
在C语言学习过程中,大家或许听到过左值和右值的概念,甚至在调试程序时编译器也会给出” left operand must be l-value ” 即左操作数必须为左值!今天我们将为大家详细解释这两个词,以及两者的区别!
简单而言,在赋值运算符“=”左边的就是左值,在赋值运算符“=”后边的就是右值,感觉像是废话,但非常好理解。但更多时候,我们是为了学习和理解不同情况下左值和右值的区别,下面来举例依次说明,着层深入,来让大家解渴!
变量做左值和右值的区别:
如 x = 2;
这里x为整形变量,这里作为左值,代表的是一块内存单元,表示的是地址。
再如x = y;
现在看变量做右值情况,y做右值,这里呢就不在表示地址,而是代表该内存单元上的值!然后赋给x。
常量做左值和右值的区别:
继续 x = 2;
这里2做右值, 2是一个常量,没有任何疑问。
而如果 1 = 2;
这里我们看左值,是1是常量,这里就会有问题了,编译会报错!因为常量不可被修改、不可以被赋值!所以大家可能会听过或见过”可修改/不可修改的左值”。
C语言中左值和右值的区别
数组名做左值和右值的区别:
例如有字符数组char a[100];
当a做右值时候,我们可以把它赋给char *类型的指针,用来指向这个数组,这种情况下数组名做右值代表该数组首元素的首地址,是常量,是完全可以的。
而数组名无论右值和还是左值,都代表是地址,是常量,因此它不可以做左值,因为常量不可被修改!所以不少同学试图再定义数组之后再试图对数组赋字符串都是错误的!
C语言中左值和右值的区别
字符串常量做右值
字符串常量想必大家都很清楚,是用双引号括起来的字符串,既然也是常量,也理所当然不可以做左值,但做右值呢?
答案是,会表示该字符串在内存中存储位置的首地址。就是char * p = “dotcpp.com”;用法的原因。
原文地址
https://www.cnblogs.com/foreverW/p/6684276.html
第一次让左值右值引起我注意的时候是在刚接触字符串和指针的时候编译器对代码的一段错误提示
那什么是左值(l-value)那:
说的通俗一点就是可以放在赋值号左边的叫左值 就是可以被赋值的。是一个地址
左值一般是是一个变量可以被赋值的变量。(const变量是一个例外只能做右值)
那什么是右值(r-value)那:
同样我们可以说是可以放在赋值号右边的 就是可以给其他变量赋值的,
它可以是一个变量也可以是一个常量也可以是一个表达式。是一个内容
例如:
#include<stdio.h>
int main()
{
char name[20];
char *adress;
name="小明"; //错误的
adress="南极"; //正确的
}
name="小明";
这个语句中 字符数组 name 就不是一个左值 因为name 在定义的时候它是被分配道内存的栈中,
而 "小明" 是存储在内存的静态常量中 ,它在赋值的时候是将这个静态区的常量的首地址赋給一个指针变量,
所以name 字符数组不能做这里的左值 而且 name 本质上是一个数组 是将每个字符存储在单元格中 ,
虽然在按字符串格式输出的时候是一段字符串,但是实际上它本质上也是一个一个字符组到一起的。
如果要把一段字符串存储在字符数组中就需要把一个一个字符存储在数组中。
什么是表达式:
表达式由一个或多个操作数通过操作符组合而成。最简单的表达式仅包含一个字面值常量或变量。较复杂的表达式则由操作符以及一个或多个操作数构成。
一个变量是表达式但是一个表达式就不一定是变量了。
确切一点说一个简单的赋值语句
左值是一个地址 左值是左侧表达式所代表的地址
右值是右侧表达式所代表的内容。
但左值并不一定能被赋值,因为左值可以引用某个常量。 所有的引用都是左值。
右值是表达式的值(不是引用),可以放在赋值右面。
所以所有左值都可以做右值。
函数的引用参数
把参数声明成引用,实际上改变了缺省的按值传递参数的传递机制。在按值传递时,函数操纵的是实参的本地拷贝。当参数是引用时,函数接收的是实参的左值而不是值的拷贝。
这意味着函数知道实参在内存中的位置,因而能够改变它的值或取它的地址。