什麼是左值(lvalue)和右值(rvalue)?
隨著學習的深入,你會經常看到 lvalue 這個詞。
一般出現在諸如各種、書籍中,更頻繁遇到的是在你的錯誤提示中:
一般你會看到這個是因為你的代碼這麼寫:
……
int i;
5 = i;
……
一些朋友想當然的就覺得 lvalue 指的就是賦值運算符左邊的那個值,而 rvalue 當然就是右邊那個值啦。
所以我們親切的稱呼它們為「左值」和「右值」。
你也是這麼想的,對吧?
事實上這樣理解並不全面,並且常常容易犯思想上的錯誤……
OK,今天小甲魚就嘗試給 lvalue 正名!
首先,我們找到 C 語言的作者問問究竟,他是這麼說的:
《The C Programming Language》
"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."
看到這裡,大家就會說了,這不明擺著嗎?人家作者都說了,E1 = E2,這個 E1 就是 lvalue(左值),你還鬧騰個啥?
因為 C 語言是在不斷發展的,畢竟老頭的這本書說的是 C 語言的原型,自 1988 年第二版之後就沒有再出新版了。而 C 的標準則經歷了 K&R C,C89,C90,C99,C11 的迭代……
好吧,我們找來了目前最廣泛使用的 C99 標準:
The name "lvalue" comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. 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".
這裡說的很清楚了,lvalue 這個名字最初確實來自於 E1 = E2(E1 就是那個可改變的左值)。但更合理的解釋應該是將 lvalue 理解為 locator value(特定位置的值),rvalue 則應該是 value of an expression(表達式的值)。
所以,單純用左邊(left-value)和右邊(right-value)來理解是不全面的。
請嘗試執行下邊代碼:
#include <stdio.h>
int main()
{
int a = 5;
++(a++);
return 0;
}
你會得到下邊錯誤提示:
在這裡如果你認為 lvalue 只是賦值運算符左邊那個值,那這個錯誤提示就無法理解了。
但是如果你知道 lvalue 是用於識別或定位存儲位置的標識符,那麼就好解釋了:
(a++) 是先將變量 a 的值(5)做為整個表達式的值返回,再將 a 自增 1(類似於 a = a + 1)。
所以這裡 ++(a++); 相當於 ++(5), a = a + 1;
那當然要報錯啦,5 是一個常量,當然不能給你 5 = 5 + 1 咯~
好了,差不多是這樣了,謝謝大家花時間聽小甲魚扯淡~
重要的內容要重複強調:C 語言的術語 lvalue 指用於識別或定位一個存儲位置的標識符。(注意:左值同時還必須是可改變的)
噢,對了,說了這麼多,應該說說 rvalue 了吧?
其實 rvalue 的發明完全是為了搭配 lvalue,rvalue 你可以理解為 readable value,即任何可讀取的值都被認為是右值(非左值)。