免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: kernelxu
打印 上一主题 下一主题

关于左值"lvalue"和右值"rvalue"的一点理解 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2006-05-05 19:15 |只看该作者
非常高兴和您继续探讨!

>> i = foo();          /*function call是表达式,函数调用foo()不是"lvalue"但在这里也不能作为"rvalue"*/

之所以不能这样赋值是因为类型的问题:函数 foo() 的返回值为 void,而 i 的类型为 int。如果单独调用函数的话 foo();,那函数返回的就是一个右值。


这里我觉得其实质原因不是类型的问题,而是本身void类型的值不能作为"rvalue"来使用。

标准中没有提到可以用void来定义变量,所以
  1. void num;
  2. 这样的定义是非法的。
复制代码

the void type的用法主要有:
《C:A Reference Manual 》fifth edition, P168 5.9 The void Type:
(1) as the return type of a function, signifying that the function returns no value;
(2) in a cast expression when it is desired to explicitly discard a value;
(3) to form the type void *, a "universal" data pointer; and
(4) in place of the parameter list in afunction declarator to indicate that the function takes no arguments.

如果仅仅是类型的问题话,那么我引入cast operator是否就应改产生"rvalue"呢?但是
void foo(void)
{
   /*do something...*/
}

int i;
i = (int)foo();

这样也是不行的,而有另外一个例子:
  1. int num;
  2. num = (void)100;
复制代码

(void)100是合法的,但是这样将他作为"rvalue"就是非法的。

然后,"rvalue"的定义为"the value of an expression",但是
void as the return type of a function, signifying that the function returns no value;

所以我觉得单独的返回值为void的函数调用也不是"rvalue",而是"not a "lvalue" "。

[ 本帖最后由 kernelxu 于 2006-5-5 19:17 编辑 ]

论坛徽章:
0
12 [报告]
发表于 2006-05-05 19:30 |只看该作者
从编译器的角度理解往往事倍功倍,比纸上说什么都强

void n ;     为什么会出错?

抛弃什么左值,右值的概念,从编译器角度看,void 是什辅助性的修饰,那么编译器是无法为void型的变量为配空间的。

当然,编译器也无法为
    int i = (int)foo();    获得数据,应此,编译器肯定无法工作。


(void)100; 那么编译器如何处理呢? 编译器将抛弃100这个值。这是可以理解的。


*mystrcp() = 'c';  那么编译器将参引 *里的值;这是一个地址值,往地址里放东东,是可以理解的。

反过来看:

&i = 1;      &i 的值是数值型的东东,当然编译器无法处理了。

论坛徽章:
0
13 [报告]
发表于 2006-05-05 20:01 |只看该作者
>> 我觉得单独的返回值为void的函数调用也不是"rvalue",而是"not a "lvalue" "。

根据左值的定义,我们已经知道是不存在 void 类型的左值的。再看看标准对 void 类型的说明:

The void type comprises an empty set of values; it is an incomplete type that cannot be
completed. (C99 6.2.5-19)

这是说类型为 void 的对象实际上是不存在的。尽管 void 表示 no value (或者是 empty),这一状态也可以看作是一种特殊的 value。

而且你在前面也说过:An expression that is not an l-value is sometimes called an r-value。一个表达式的结果要么是左值,要么是右值,二者必居其一(也就是我前面说过的“非左即右”,这在 C++ 标准中是有明确规定的:Every expression is either an lvalue or an rvalue)。而结果类型为 void 的表达式不可能是左值(如你上面所说的"not an "lvalue" "),所以必然是右值。

论坛徽章:
0
14 [报告]
发表于 2006-05-05 21:02 |只看该作者
讨论得很有意思,其实有时候争论往往会以聚焦到一个概念而告终,我们争论的最后一个焦点就是:
一个表达式究竟是非左值即右值,还是还存在另一种非左值也非右值的值呢
我觉得到这个层面如何归类应该视上下文环境来看。

根据左值的定义,我们已经知道是不存在 void 类型的左值的。再看看标准对 void 类型的说明:

The void type comprises an empty set of values; it is an incomplete type that cannot be
completed. (C99 6.2.5-19)

同意。
这是说类型为 void 的对象实际上是不存在的。尽管 void 表示 no value (或者是 empty),这一状态也可以看作是一种特殊的 value。

这样理解也无妨。
而且你在前面也说过:An expression that is not an l-value is sometimes called an r-value。

这是《C:A Reference Manual 》fifth edition的解释,而且这里有sometimes。
一个表达式的结果要么是左值,要么是右值,二者必居其一(也就是我前面说过的“非左即右”,这在 C++ 标准中是有明确规定的:Every expression is either an lvalue or an rvalue)。而结果类型为 void 的表达式不可能是左值(如你上面所说的"not an "lvalue" "),所以必然是右值。

可能C++是如此,但是在C标准中对有些表达式都只是说
"is not a lvalue"

而没有直接说
"is a rvalue"

例如:
《ISO/IEC9899 WG14/N1124》6.3.2.1
...an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue).
...an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.

而且,C标准没有明确定义"rvalue"(只在脚注中提到)
《ISO/IEC9899 WG14/N1124》6.3.2.1
What is sometimes called ‘‘rvalue’’ is in this International Standard described as the ‘‘value of an expression’’.

"rvalue"只是帮助更好地理解"lvalue"而出现,所以标准中不是"lvalue"都以"no lvalue"来表述。
所以我相信这个not a lvalue不仅包括"rvalue"还包括"no value and no rvalue"的一类。

其实,到这里只是个人理解不一样而已,因为标准也像其他很多东西一样并没有精确定义。
很高兴和你探讨。:)

论坛徽章:
0
15 [报告]
发表于 2006-05-05 21:14 |只看该作者
原帖由 mik 于 2006-5-5 19:30 发表
从编译器的角度理解往往事倍功倍,比纸上说什么都强

void n ;     为什么会出错?

抛弃什么左值,右值的概念,从编译器角度看,void 是什辅助性的修饰,那么编译器是无法为void型的变量为配空间的。

当然 ...



呵呵,其实我觉得编译器只是标准的实现而已,一个自称和标准conformable的编译器应该遵循标准明确定义的rules,而将其他的功能作为extensions。

从编译器的角度理解往往事倍功倍,比纸上说什么都强

编写编译器的人需要熟读和理解标准的每一句话,编译器有成千上万,而一种语言的标准只有一种,谁是根源呢?
void n ;     为什么会出错?

抛弃什么左值,右值的概念,从编译器角度看,void 是什辅助性的修饰,那么编译器是无法为void型的变量为配空间的。

当然,编译器也无法为
    int i = (int)foo();    获得数据,应此,编译器肯定无法工作。


(void)100; 那么编译器如何处理呢? 编译器将抛弃100这个值。这是可以理解的。

实际上是标准命令编译器这么干的。

*mystrcp() = 'c';  那么编译器将参引 *里的值;这是一个地址值,往地址里放东东,是可以理解的。

反过来看:

&i = 1;      &i 的值是数值型的东东,当然编译器无法处理了。

能不能这样用是由assignment operator的属性决定的,赋值运算要求其left operand是modifiable lvalue,
right operand 是rvalue。
因为
*mystrcp() = 'c';
*mystrcp() 是lvalue;且'c'是rvalue
int i;
&i = 1;
&i is not a modifiable lvalue.

[ 本帖最后由 kernelxu 于 2006-5-5 21:25 编辑 ]

论坛徽章:
0
16 [报告]
发表于 2006-05-05 21:26 |只看该作者
我是从编译器角度理解标准 :)

论坛徽章:
0
17 [报告]
发表于 2006-05-05 22:57 |只看该作者
讨论得很有意思,其实有时候争论往往会以聚焦到一个概念而告终,我们争论的最后一个焦点就是:
一个表达式究竟是非左值即右值,还是还存在另一种非左值也非右值的值呢
我觉得到这个层面如何归类应该视上下文环境来看。

根据左值的定义,我们已经知道是不存在 void 类型的左值的。再看看标准对 void 类型的说明:

The void type comprises an empty set of values; it is an incomplete type that cannot be
completed. (C99 6.2.5-19)

同意。
这是说类型为 void 的对象实际上是不存在的。尽管 void 表示 no value (或者是 empty),这一状态也可以看作是一种特殊的 value。

这样理解也无妨。
而且你在前面也说过:An expression that is not an l-value is sometimes called an r-value。

这是《C:A Reference Manual 》fifth edition的解释,而且这里有sometimes。
一个表达式的结果要么是左值,要么是右值,二者必居其一(也就是我前面说过的“非左即右”,这在 C++ 标准中是有明确规定的:Every expression is either an lvalue or an rvalue)。而结果类型为 void 的表达式不可能是左值(如你上面所说的"not an "lvalue" "),所以必然是右值。

可能C++是如此,但是在C标准中对有些表达式都只是说
"is not a lvalue"

而没有直接说
"is a rvalue"

例如:
《ISO/IEC9899 WG14/N1124》6.3.2.1
...an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue).
...an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.

而且,C标准没有明确定义"rvalue"(只在脚注中提到)
《ISO/IEC9899 WG14/N1124》6.3.2.1
What is sometimes called ‘‘rvalue’’ is in this International Standard described as the ‘‘value of an expression’’.

"rvalue"只是帮助更好地理解"lvalue"而出现,所以标准中不是"lvalue"都以"no lvalue"来表述。
所以我相信这个not a lvalue不仅包括"rvalue"还包括"no value and no rvalue"的一类。

其实,到这里只是个人理解不一样而已,因为标准也像其他很多东西一样并没有精确定义。
很高兴和你探讨。:)

论坛徽章:
0
18 [报告]
发表于 2006-05-05 23:42 |只看该作者
>> C标准没有明确定义"rvalue"(只在脚注中提到)
>> 因为标准也像其他很多东西一样并没有精确定义。

确实是这样的,特别是对于 C 语言来说更是如此。

正因为 "rvalue" 不是在 C 标准正文中规定的正式术语,所以在标准中出现的时候也尽量避免使用这个术语,而是一般说成“not an lvalue” 或者其它否定形式。

可能对此有不同的看法,不过我认为可以把 “not an lvalue” 等价于 rvalue。在 IBM 提供的资料上看到这么一句话:Rvalues always have complete types or the void type. 支持我的上述看法。不管 C 标准是怎么对待 rvalue 的,实际中它已经变成了一个正式用语。

>> 能不能这样用是由assignment operator的属性决定的,赋值运算要求其left operand是modifiable lvalue,right operand 是rvalue。

还要再加上一个条件,即左右操作数的类型是否一致,或者右操作数的类型是否可以默认转换为左操作数的类型。

>> &i = 1;
>> &i is not a modifiable lvalue.

更严密的说法是:&i is not an lvalue。或者直接说 &i is an rvalue。

论坛徽章:
0
19 [报告]
发表于 2006-05-06 12:56 |只看该作者
原帖由 whyglinux 于 2006-5-5 23:42 发表
>> C标准没有明确定义"rvalue"(只在脚注中提到)
>> 因为标准也像其他很多东西一样并没有精确定义。

确实是这样的,特别是对于 C 语言来说更是如此。

正因为 "rvalue" 不 ...
>> C标准没有明确定义"rvalue"(只在脚注中提到)
>> 因为标准也像其他很多东西一样并没有精确定义。

确实是这样的,特别是对于 C 语言来说更是如此。

正因为 "rvalue" 不是在 C 标准正文中规定的正式术语,所以在标准中出现的时候也尽量避免使用这个术语,而是一般说成“not an lvalue” 或者其它否定形式。

可能对此有不同的看法,不过我认为可以把 “not an lvalue” 等价于 rvalue。在 IBM 提供的资料上看到这么一句话:Rvalues always have complete types or the void type. 支持我的上述看法。不管 C 标准是怎么对待 rvalue 的,实际中它已经变成了一个正式用语。


嗯,其实有这么多不同的理解就是由于标准没有定义清楚的缘故。只要基本意思一样也就无妨了。而且有的两种理解的同时存在呢,呵呵。刚刚从whyglinux兄所给的IBM链接找到这么一句话(不过是针对C++的),还是觉得理解第一吧,呵呵。
链接是IBM AIX Compiler Information(感谢whyglinux提供这么好的资源链接)
On the other hand, in C++, a function call that returns a reference is an lvalue. Otherwise, a function call is an rvalue expression. In C++, every expression produces an lvalue, an rvalue, or no value.


>> 能不能这样用是由assignment operator的属性决定的,赋值运算要求其left operand是modifiable lvalue,right operand 是rvalue。

还要再加上一个条件,即左右操作数的类型是否一致,或者右操作数的类型是否可以默认转换为左操作数的类型。


嗯,谢谢指出。
>> &i = 1;
>> &i is not a modifiable lvalue.

更严密的说法是:&i is not an lvalue。或者直接说 &i is an rvalue。

好,接受。谁让我在 &i = 1; 前明确加了一个 int i; 呢。呵呵。

[ 本帖最后由 kernelxu 于 2006-5-6 13:37 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP