关于“左值”

记得以前看到一篇文章,介绍什么是“左值”,“左值”有什么样的限制:
1、常量表达式不能成为左值;
2、临时对象不能成为左值;
3、const修饰的变量不能成为左值;
……

看到“左值”这个概念的时候,让人觉得有些诧异。
“左值”,顾名思义就是等号左边的值。说白了,就是在一个表达式中要被写的那个值。但是我觉得“左值”这个概念实在太故弄玄虚,给人的第一感觉是,“因为这个值在左边,所以它要接受限制”。(这是什么逻辑……)
然而,如果取个本份点的名字,比如“被写值”呢?因为这个值将被写,所以它要接受一些限制。

1、不允许改写常量表达式,否则多次执行同样一段代码可能得到不同的结果。
如果常量字符串"hello world"会被改写,那么printf("hello world");可能没法将"hello world"给print出来。这样的逻辑不是很匪夷所思吗?
所以,一般常量字符串会被编译器放在程序的只读数据段中,由内核来保证它们不可写。(当然,C标准并没有规定编译器一定要这么做。标准只是说,写常量字符串将得到一个不可预知的结果。)

2、不允许写编译器产生的临时对象,因为这样的写操作是无意义的。
在C/C++中,使用常规手段是无法访问到临时对象的(当然存在非常规的办法)。写过之后临时对象再也没有被读的机会了,写了干什么呢?
如果偏要写呢?那应该倒没什么关系,不过就是在运行栈写一些信息而已。

3、不允许写const变量,因为这是程序主动申请的限制。
编译器的作用并不仅仅是把源代码编译成目标代码,它还需要有源代码的查错机制。所有这些限制都是为程序的逻辑服务的,这就是高级语言的高级之处。
(记得大学时教《编译原理》的教授曾说过,编译错误永远只是小问题,因为不需要你思考,错误都让编译器都给你找出来了。而我们写程序应该把编译器的查错功能利用起来,尽可能的把错误暴露给编译器;而不是想办法欺骗编译器,让它帮你编译出漏洞百出的目标代码。)

显然,以上这些限制,都是因为“值”要被写而造成的,并不是因为“值”在左边。

后来发现,关于“左值”和“右值”,还有另外一种释义。“左值”(l-value)实际上是“存储(可写)地址”(location value)、“右值”(r-value)实际上是“读地址”(read value)。这个解释倒是贴切多了~

时间: 2025-01-26 12:17:13

关于“左值”的相关文章

求解答关于左值的问题。

问题描述 求解答关于左值的问题. 编译器报错error C2105: '++' needs l-value,见源程序 (p+len-1)=(p+len-1)+1为什么不能用*(p+len-1)++代替呢? #include <stdio.h> int main() { int a[10]={0}; int len; int i; int *p=a; char *ptr2; char s[500]; int sum =0; char *ptr; gets(s); ptr=s; while(*pt

C++中关于左值和右值的讨论

左值性(lvalueness)在C/C++中是表达式的一个重要属性.只有通过一个左值表达式才能来引用及更改一个对象(object)的值.(某些情况下,右值表达式也能引用(refer)到某一个对象,并且可能间接修改该对象的值,后述). 何谓对象?如果没有明确说明,这里说的对象,和狭义的类/对象(class/object)相比,更为广泛.在C/C++中,所谓的对象指的是执行环境中一块存储区域(a region of storage),该存储区域中的内容则代表(represent)了该对象的值(val

关于c++(表达式必须是可修改的左值)

问题描述 关于c++(表达式必须是可修改的左值) 代码如下,在一个类里定义了如下private型成员变量和成员函数,但是在成员函数里给vals赋值时会提示表达式必须是可修改的左值,请问是为什么呢? private: char vals[3000]; int numDigits; BigInt multDigit(char digit) const { int temp; vals = digit; } 解决方案 caozhy的回答是正确的. 补充一点: vals是数组名,digit是字符变量,不

C++中的左值和右值

在C/C++中,左值(lvalue)和右值(rvalue)是用于规定表达式(expression)的性质.C++中表达式要不然是左值,要不然是右值. 这两个概念在C语言中比较容易理解:左值能放在赋值语句的左边,右值不能.但是当来到C++时,二者的理解就比较复杂了(PS:有对象真是麻烦) 简单的归纳: 当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份即在内存中的地址. 左值是代表一个内存地址值,并且通过这个内存地址,就可以对内存进行读并且写(主要是能写)

c语言-C语言字符是左值 为什么可修改

问题描述 C语言字符是左值 为什么可修改 #include using namespace std; int main() { char c[6] = "hello"; c = "s"; //为什么c是不可被修改的左值 c[2] = 's'; //而c中的元素都可以被修改? return 0; } 解决方案 数组名是常量型指针,即 const ,当然不能修改:这个与 const 型常量是一样的,定义了就不能修改. c 中的元素,是编译器在堆栈上分配的一块内存,当然可

c++-关于函数参数左值与右值?

问题描述 关于函数参数左值与右值? 这里:string s1(""hi"")s2s3;s2=std::move(string(""bye""));//正确:从一个右值移动数据s3=std::move(s1);书上说:在s2中传递给move的实参是string的构造函数的右值结果--string(""bye"").那可不可以直接传递""bye"" 呢

左值右值讨论-c++匿名对象的左值右值问题谈论

问题描述 c++匿名对象的左值右值问题谈论 c++中返回一个匿名对象到底应该是是左值还是右值?自己写的一个重载+函数,返回一个匿名对象是左值,可是以前记着有人说过是右值的.比如class A;A abc;然后我重载了一下+,结果是如果返回值不加const竟然可以直接被赋值(a+b) = c;编译竟然通过了.但是我以前理解匿名对象本身就应该是右值啊?想问一下匿名对象到底是左值还是右值还是不确定? 解决方案 http://www.cnblogs.com/catch/p/3500678.html 解决

c++-C++中的左值/右值引用问题

问题描述 C++中的左值/右值引用问题 int getInt() { int a = 3; return a; } int& getIntR() { int a = 3; return a; } int getRL() { return 1; } int&& getRRL() { return getRL(); } int main() { // 正确,以返回的临时变量初始化a int a = getInt(); // 正确,以返回的值初始化a int b = getIntR();

c++表达式必须是可修改的左值

问题描述 c++表达式必须是可修改的左值 是public变量 为什么不能修改? 解决方案 filename是字符数组名,数组名是常量,不可以修改 解决方案二: node->getdata()=num; int Node::getdata() { return data; } num无法赋值啊!一般都是该类内函数的问题 改为node->setdata(num) void Node::setdata(int n) { data = n; }......答案就在这里:error:表达式是必须修改的左