r-value 和 l-value

        在写引用类型与指针的比较这篇随笔的时候,我写了一些试验性的代码以检验一些结论是否正确。
        首先,引用是一个const的指针(注意不是指向const object的指针),所以在声明一个引用的同时必须对这个引用进行初始化。因此

int &b;

编译不能通过是自然而然的事情,错误信息是:references must be initialized。多事的我就想,既然是const的指针,那我能不能这么写呢:

int   *   const  b; 

结果错误信息变成了const object must be initialized if not extern。接着我再

给这个statement加了个extern。OK,编译错误没有再出现了,接着,我给这个指针进行赋值。结果出现了这样的编译错误:
        l-value specifies const object

        到此为止,我看到了一个似懂非懂的东西l-value。 到底什么是l-value呢?我第一时间想到左结合了,譬如说"hello" + "world" + "!" 等价于("hello" + "world") + "!"。由此推广,我可以想到的左值的一个解释就是:在赋值的时候,"="运算符左边的就是左值了。
        而事实上,我的猜测也是基本正确的。左值必须引用于某个对象,而对于赋值运算符,它的左操作数必须是一个左值(lvalue expression must refer to an object.For the assignment to be valid, the left operand must refer to an object-it must be an lvalue. [1] );而右值(rvalue)则是具体的数字型或是字符型的值(Every expression is either an lvalue or an rvalue." So an rvalue is any expression that is not an lvalue. [1])。
      
        以下是对于左值和右值在使用上的几个要点:
        1、右值是不能转化为左值的,而反过来,则是可以的。如:    

int  a, b;
=  b;

              a和b都是左值,但是b出现在了赋值运算符的右边。编译器在编译过程中做了左值到右值的转换。

    
        2、"+"运算符的操作数没有左值或是右值的限制,但是运算的结果却是右值。比如说:

(m  +   1 =  n;

              是会发生编译错误的,因为m + 1是右值;
        3、"&"运算符的操作数必须是左值,而结果也是右值(注意这是取址运算符哦,别跟引用搞混了);
        4、"*"运算符的操作数则左值或着右值,其结果则是左值,如

int  a  =   2 ;
int   * =   new   int [ 3 ];
* =  a;
* (p + 1 =   3 ;

 

 

 

//*************************************************************************

//  MSDN的解释

//*************************************************************************

L-Value and R-Value Expressions

Expressions that refer to memory locations are called "l-value" expressions. An l-value represents a storage region's "locator" value, or a "left" value, implying that it can appear on the left of the equal sign (=). L-values are often identifiers.

Expressions referring to modifiable locations are called "modifiable l-values." A modifiable l-value cannot have an array type, an incomplete type, or a type with the const attribute. For structures and unions to be modifiable l-values, they must not have any members with the const attribute. The name of the identifier denotes a storage location, while the value of the variable is the value stored at that location.

An identifier is a modifiable l-value if it refers to a memory location and if its type is arithmetic, structure, union, or pointer. For example, if ptr is a pointer to a storage region, then *ptr is a modifiable l-value that designates the storage region to which ptr points.

Any of the following C expressions can be l-value expressions:

  • An identifier of integral, floating, pointer, structure, or union type

  • A subscript ([ ]) expression that does not evaluate to an array

  • A member-selection expression (–> or .)

  • A unary-indirection (*) expression that does not refer to an array

  • An l-value expression in parentheses

  • A const object (a nonmodifiable l-value)

The term "r-value" is sometimes used to describe the value of an expression and to distinguish it from an l-value. All l-values are r-values but not all r-values are l-values.

Microsoft Specific

Microsoft C includes an extension to the ANSI C standard that allows casts of l-values to be used as l-values, as long as the size of the object is not lengthened through the cast. (See Type-Cast Conversions for more information.) The following example illustrates this feature:

Copy
char *p ;
short  i;
long l;

(long *) p = &l ;       /* Legal cast   */
(long) i = l ;          /* Illegal cast */

The default for Microsoft C is that the Microsoft extensions are enabled. Use the /Za compiler option to disable these extensions.

END Microsoft Specific

//

//***************************************************************************************

你可能感兴趣的:(c/c++)