標籤:
http://www.cnblogs.com/dejavu/archive/2012/09/02/2667640.html#commentform
<C/C++> 左值和右值, 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
[轉] 左值和右值