左值和右值, L-value和R-value


一直以為左值是可以出現在賦值表達式左邊(the left side of an assignment expression)的值,Left-value;右值即Right-value.

今天看到一個說法,覺得有點味道:

L-value中的L指的是Location,表示可尋址. The "l" in lvalue can be thought of as location.
R-value中的R指的是Read,表示可讀. The "r" in rvalue can be thought of as "read" value.

 

為了尋找lvalue術語的出處,先是<The C Programming Language>中,Kernighan and Ritchie寫道:

"An object is a manipulatable region of storage; an lvalue is an expression referring to an object.

...

The name 'lvalue' comes from the assignment expression E1 = E2 in which the left operand E1 must be an lvalue expression."

然后我又不畏艱險,硬着頭皮翻看C99標准和<The New C Standard>這本書,想從中查找點蛛絲馬跡:

The name “lvalue” comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue.
Or left value of assignment. The right value being called the rvalue. This is translator writers’ terminology that the C Standard committee has adopted.

...

It is perhaps better considered as representing an object “locator value”.

...

What is sometimes called “rvalue” is in this International Standard described as the “value of an expression”.

似乎缺乏一個統一且明確的標准定義. 不過可以看出,左值原來定義的確跟賦值表達式左側有關,但更好的定義是"內存中,有特定位置(地址)的東西"或"指向一個確定對象的東西".

 

 

許多語言中,一個對象(object)只允許通過表達式(assignment)來修改.而C語言更靈活,它允許可以通過操作符(operator)來修改對象的值,而不僅僅是通過表達式(如++自增操作符).這就讓清楚地區分左值和右值的含義變的很重要,如

  int a = 10;
  ++(a++); //error!

編譯器(gcc)會報錯:error: non-lvalue in increment (非左值自增)

如果能清楚的理解,左值(lvalue)是一個"擁有一個可以確定的地址(指向一個對象)"的標識符或表達式,而右值(rvalue)只是一個值,並不一定指向一個對象.那這個問題就簡單了:

(a++)表達式 是先將a的值做為整個表達式的值返回,再將a自增1.那么,(a++)表達式的值並不指向一個對象(不擁有一個內存地址),因為它類似 

{
  int
temp = a;   a = a+1;   return temp;
}

temp是臨時值(如某個寄存器),它並不指向一個對象(temp並沒有分配實際的地址).所以(a++)表達式不是左值!之后,++(a++)相當於對一個右值(非左值)進行自增(++temp)當然是不合理的!

但是,注意!后綴增量表達式返回值一定是個非左值,但前綴增量表達式呢? 前綴增量表達式的返回值對於C和C++是不同的:

  int a = 10;
  (++a)++; //C++ ok,C error!
  ++(++a); //C++ ok,C error!
  (a+=1)+=1; //C++ ok,C error!

對於上述代碼,gcc是報錯,而g++是通過!

原因在於,C中,前綴增量表達式(prefix increment)返回的是非左值(C標准6.5.3.1 The expression ++E is equivalent to (E+=1).並且在6.5.16 An assignment expression has the value of the left operand after the assignment, but is not an lvalue. )(這也說明了C語言中(a=1)=2,這樣的連用是錯誤的!)

但在C++中,已經明確定義前綴增量表達式返回值為一個左值(C++標准5.3.2.1 The value is the newvalue of the operand; it is an lvalue.).所以對(++a)再做一次前++或后++沒問題.(而且賦值表達式返回也是左值,所以(a=1)=2連用沒問題)

 

另外,

在C中,一個表達式要么是左值要么是非左值,沒有右值說法,直到C++時,右值才被正名.

左值不一定是可以修改的值,如一個const對象是左值,但不能被修改(non-modifiable lvalue).

右值可以是左值和非左值.

 

 

其他參考:

http://www.cppblog.com/cc/archive/2012/06/27/7619.html

http://eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues

http://stackoverflow.com/questions/3572753/difference-between-cs-expression-and-cs-expression

http://homepage.ntlworld.com/dmjones/cbook1_2.pdf


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM