汗 好纠结的左值啊

slowgrace 2009-10-17 09:25:50
这个帖子里其实讨论过这个问题了,但是感觉我的纠结表达得不够清晰,所以重新发一遍问题,请先看仔细我思考的过程,再给出回答,谢谢关注!

(1)
Q:作为一个程序员,为什么要弄明白左值的概念?
A:有很多原因。比如说,下列运算符的操作数要求左值:Sizeof运算符, 取地址运算符 & , ++ 运算符, -- 运算符,赋值 = 运算符的左侧,成员 . 运算符的左侧。如果你不知道哪些表达式是左值,你就可能给错。

(2)
Q:那么如何判断一个表达式是左值?
A:依据标准的定义来判断。

(3)
Q:那么标准对左值的定义是什么?
A:An lvalue is an expression with an object type or an incomplete type other than void; 也就是说,如果一个表达式具有对象类型或非空不完整类型,那就是左值。

(4)
Q:那么如何判断一个表达式具有对象类型?
A:具有对象类型的意思是说,这个表达式可以引用一个对象。

(5)
Q:那么如何判断一个表达式可以引用一个对象?
A:如果这个表达式的结果可以拥有你可以访问的存储。

(6)
Q:那么如何判断一个表达式的结果“可以拥有你可以访问的存储”?
A:……


另一个分支
(4)
Q:那么&a是对象类型,为何说它不是左值呢?
A:因为&a只是一个值,没有引用对象啊?

(5)
Q:为什么说&a没有引用对象?
A:因为&a只是一个表达式的值,没有任何存储空间存储这个值。

(6)
Q:依据什么知道&a没有任何存储空间呢
A:……

请问两个(6)的答案,谢谢。
...全文
559 74 打赏 收藏 转发到动态 举报
写回复
用AI写文章
74 条回复
切换为时间正序
请发表友善的回复…
发表回复
slowgrace 2009-10-20
  • 打赏
  • 举报
回复
结帖了,谢谢楼上各位,尤其是几位被俺“纠缠”多日的朋友。

小结在这里:http://blog.csdn.net/slowgrace/archive/2009/10/20/4704066.aspx
slowgrace 2009-10-20
  • 打赏
  • 举报
回复
谢谢木头的发言。
捧剑者 2009-10-19
  • 打赏
  • 举报
回复
汇编语言、计算机组成原理、操作系统原理也可以看看;
虽然本来讨论的都是C、C++的问题,但是正如科学和人生的很多问题一样,在更大的范围上去把握或许能有另一番天地。功夫不妨在诗外。
捧剑者 2009-10-19
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 slowgrace 的回复:]
引用 12 楼 hpsmouse 的回复:
编程毕竟不是数学~~


编程不是数学。但是编译器是机械的、有确定结果的、依据规则进行的、行为不随意的……

在程序的世界里,一切现象都应该依据某种规则得到解释。如果某个现象无法得到进一步的解释,那么它本身就是规则。

如果有个人告诉我,我在问的问题本身是规则,那么我就不会再问下去了
[/Quote]
总的来说,就是规则。
一般的教材中对常见的情况都有清楚的表述。完整的表述要找一些大部头的来看,对于什么时候需要左值,什么情况下会产生左值都能查到。如果对这些语法问题十分感兴趣,不妨找来翻翻。
至于规则为什么要如此如此的制定,而不是那样那样的样子,其实也是有很深的道理。如果感兴趣,可以看看《The Design and Evolution of C++》以及编译原理类的书,以及不妨多涉猎几种程序设计语言,比较它们的异同,或许能有所悟,有更深的理解,对使用你主攻的语言也一定会有帮助。
不过,常用的没几个,错了编译器也会有提示,程序写多了就熟悉了有语感了,不查手册自己也能猜个八九不离十了。
leon_hit 2009-10-19
  • 打赏
  • 举报
回复
之所以引发疑惑,是因为有许多变量既可以作为左值,又可以作为又值。例如表达式:a = a + b 中,右方的a作为右值,左边的a作为了左值。就我的经验而言,对于一个变量而言,你用到的是它的地址就是左值,仅用到它的值就是右值。比如例中,右方的a只用到字面值,而左方的a则提供了一个结果的存储地址,是个左值。
stardust20 2009-10-19
  • 打赏
  • 举报
回复
强大。。。。
mymtom 2009-10-18
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 milkylove 的回复:]
我是这么理解的:一个表达式是否拥有“可以拥有你可以访问的存储”,那要看这个表达式的返回值是什么。如果表达式返回的不是一个引用,返回值就被保存在一个临时对象里,这个临时对象由编译器管理,你不能插手,所以它不具有“可以拥有你可以访问的存储"。而如果返回的是引用,而引用的对象一定具有“可以拥有你可以访问的存储”。

所以,表达式是否左值,就要看表达式的最后一级运算符返回的是什否是引用。
[/Quote]
“如果表达式返回的不是一个引用”,
C语言可没有“引用”的说法啊。
神马都能聊 2009-10-18
  • 打赏
  • 举报
回复

int& fuck()
{
static int __a = 0;
return __a;
}

雷到了。
slowgrace 2009-10-18
  • 打赏
  • 举报
回复
谢谢飞雪。打饭去了,要不食堂该没饭了,下午来仔细学习。

另外fuck改成fine是不是好些
baihacker 2009-10-18
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

int main()
{
int fuckable;
reinterpret_cast<int&>(fuckable) = 123;
cout << fuckable << endl;
return 0;
}
baihacker 2009-10-18
  • 打赏
  • 举报
回复
int a = 0;
int* ptr = &a;
*a;

改成
*ptr

#include <iostream>
#include <typeinfo>
using namespace std;

template<typename T, int n>
void fuck(T (&x)[n])
{
cout << sizeof (x) << endl;
}

int main()
{
char arr1[5];
int arr2[8];
double arr3[16];
fuck(arr1);
fuck(arr2);
fuck(arr3);
cout << typeid(arr1).name() << endl;
cout << typeid(arr2).name() << endl;
cout << typeid(arr3).name() << endl;
return 0;
}
slowgrace 2009-10-18
  • 打赏
  • 举报
回复
谢谢飞雪

不过的话,到这里看看你贴的英文在我这里显示的经典效果吧。

是不是俺的屏太窄了啊?
baihacker 2009-10-18
  • 打赏
  • 举报
回复
1 The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an
object type, or a pointer to a function type and the result is an lvalue referring to the object or function to
which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.”
[Note: a pointer to an incomplete type (other than cv void ) can be dereferenced. The lvalue thus obtained
can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to an
rvalue, see 4.1. ]


int a = 0;
int* ptr = &a;
*a;

int arr[100];
arr[0];

int& fuck()
{
static int __a = 0;
return __a;
}

fuck();

extern int arr[];
arr
baihacker 2009-10-18
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 slowgrace 的回复:]
飞雪,你是不是从来不看站内短消息的啊?
[/Quote]
雷8秒前...
baihacker 2009-10-18
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 slowgrace 的回复:]
飞雪,你是不是从来不看站内短消息的啊?
[/Quote]
木有消息啊.
slowgrace 2009-10-18
  • 打赏
  • 举报
回复
飞雪,你是不是从来不看站内短消息的啊?
baihacker 2009-10-18
  • 打赏
  • 举报
回复

//哪里需要左值了?
#include <stdio.h>

int main()
{
printf("%d\n%d\n", sizeof(int), sizeof(main()));
return 0;
}
失落的凡凡 2009-10-18
  • 打赏
  • 举报
回复
逗号运算符……

从左向右依次运算各个表达式,并返回最右边的表达式
macrojj 2009-10-18
  • 打赏
  • 举报
回复
我觉得真正重要的是语义。
slowgrace 2009-10-18
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 hpsmouse 的回复:]
不知道“通过非函数类型声明的非类型标识符都是左值”正确吗?
如果正确的话,可以通过这一点加上各个 operator 的左右值属性推出那些是左值。
[/Quote]

谢谢,感觉这就是答案了,如果正确的话。
加载更多回复(54)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧