在電腦科學中,值(英語:Value)是一無法進一步求值的表達式。[1]例如,表達式「1 + 2」不是一個值,因為它可以被化簡為表達式「3」。表達式「3」不能夠繼續化簡,因此它是一個值。表達式既有類型(type)屬性,又有值分類(value categories)屬性。兩種屬性彼此獨立。[2]也就是說,對每一種類型的表達式,都有各種值分類。
此條目需要補充更多來源。 (2013年2月11日) |
大多數程式語言支援幾種常見的值。
賦值:左值和右值
一些語言使用左值(l-value)和右值(r-value)的概念。左值具有確定的、可以被獲得的主記憶體地址。這意味着左值可以是變數,也可以是對指向特定主記憶體地址的指標解除參照(dereference)的結果。例如C語言的表達式(4 + 9)
,在執行時,電腦生成一個整數值13,但因為程式沒有明確指定這個13如何在電腦中儲存,所以這個表達式產生一個右值。另一方面,如果一個C程式聲明了一個變數x並將x賦值為13,那麼表達式(x)
的值是13,並且是一個左值。
在C語言中,術語「左值」最初表示可以被賦值(即位於設定運算子左側)的對象,但由於「const」被加入到語言中,這類對象現在被稱作「可更改的左值」。C++中,左值和右值是表達式的分類,一個表達式必然是左值或右值之一。C++11把上述左值性(lvalueness)擴充為更複雜的值類別(value category),包含左值(lvalue),純右值(prvalue)和臨終值(xvalue)三個基本分類(fundamental classification),一個表達式必然是三者之一。
左值和右值的概念最早由CPL程式語言的一篇論文引入。[3] 這時定義的左值是可以放在賦值號左側賦予新值的對象;[4]右值是可以放在賦值號右側讀出其值的對象。在B語言中,左值和右值作為文法的元素被明確。在C語言中,文法不再出現左值和右值的區別,左值的概念被保留在語意規則中,而「右值」在ISO C中被視為「值」的同義詞。
C++語言引入了const限定的對象。const對象可以取地址,但是不能被賦值;而一些右值對象也可以出現在賦值號的左邊被賦值。[5]因此,截至C++03標準,把具有標識(identity)的表達式規定為左值,不具有標識的表達式規定為右值。因而,名字、指標、參照等是左值,是命名對象,具有確定的主記憶體地址;字面量、臨時對象等為右值,右值僅在建立它的表達式中可以被訪問。函數名字是左值(在C語言中規定它既不是左值也不是右值),陣列名是常數左值,但是在大多數表達式中函數名字與陣列名字自動隱式轉換為右值。右值的生存期短暫,所以需要用左值去捕捉右值。把右值複製(copy)到左值上是常見操作。
C++11標準引入了右值參照資料類型與移動語意,因而左值與右值的定義發生了很大變化。右值參照變數繫結到右值上,延長了右值對應的臨時對象的生存期。移動語意把臨時對象的內容移動(move)到左值對象上。因而在C++11,對於值的分類,要考慮標識(identity)與抽取式性(movability),二者的組合產生了五種分類:
- 基礎值類型
- 左值lvalue:可以用取地址運算子&取得地址的表達式。也可定義為非臨時對象或非成員函數。具有標識,但不抽取式。這也是C++03的經典左值。可用於初始化左值參照。可以有不完備類型(incomplete type)。包括:
- 作用域中的變數名與函數名,不論其類型。因此,具名的右值參照,即具有右值參照類型的變數,也是左值表達式,這符合一般規律,不是特例。
- 函數呼叫表達式或多載運算子表達式,如果其返回類型為左值參照或者是到函數類型的右值參照。 [6]
- 內建的先增(字首++)、先減(字首--)、解除參照(dereference)、賦值、複合賦值、下標(除了陣列臨終值)、成員訪問(除了臨終值的非靜態非參照成員、成員列舉值、非靜態成員函數),通過數據成員指標的訪問且左端運算元為左值、逗號運算子且右端的運算元為左值、三元條件運算子(ternary conditional)且第二與第三運算元為左值。
- 到左值參照類型的類型轉換表達式。
- 字串字面量(string literal)
- 類型轉換表達式,轉換為到函數的右值參照
- 臨終值xvalue(expiring value):具有標識,並且可以移動。對應的對象接近生存期結束,但其內容尚未被移走。可以多型;非類對象可以cv限定。包括:
- 純右值prvalue:不具有標識,但可以移動。對應臨時對象或不對應任何對象的值。純右值不能是多型的;臨時對象的動態型別是表達式類型;非類且非陣列的純右值不能是const限定的;不能有不完備類型(除了void)。包括:
- 字面量(除了字串字面量)。
- 函數呼叫或多載的運算子表達式,如果返回類型不是參照。[6]
- 內建後增、後減、算術與邏輯運算子、比較運算子、取地址運算子、訪問成員列舉值、訪問非靜態成員函數、訪問右值的非靜態非參照數據成員、訪問右值的數據成員指標或非靜態函數成員指標、逗號運算子且右端運算元為右值、三元條件運算子且第二或第三運算元不是左值。
- 類型轉換表達式,轉換為非參照類型。
- Lambda表達式
- 左值lvalue:可以用取地址運算子&取得地址的表達式。也可定義為非臨時對象或非成員函數。具有標識,但不抽取式。這也是C++03的經典左值。可用於初始化左值參照。可以有不完備類型(incomplete type)。包括:
- 廣義左值glvalue:具有標識。包括左值與臨終值。可以多型、動態型別。
- 右值rvalue:可以移動。包括瀕死值與純右值。不能通過&運算子取地址。
C++的非靜態成員函數呼叫表達式(obj.func與ptr->func),非靜態成員函數指標呼叫表達式(obj.*mfp與ptr->*mfp)被當作純右值,但是不能用於初始化參照,不能做函數實參,僅僅能用作函數呼叫表達式左邊的運算元,如(pobj->*ptr)(args)。
返回void的函數呼叫表達式、到void的類型轉換表達式、throw表達式被當作純右值。但是不能用於初始化參照,不能做函數實參。可用於某些上下文環境中(如單獨作為一行陳述式、逗號運算子的左端表達式等),或返回void的函數的return陳述式中。此外,throw表達式可用作三元條件運算子的第二或第三運算元。
位元欄(bit field)表達式是左值,但不能用&運算子取地址,不能繫結到非常數左值參照。常數左值參照可以用位域左值初始化,但實際上是另行分配繫結了一個對象。
匯編語言
值可以是一個給定的資料類型,例如一個字串,一個數字,一個單一的字母等幾乎任何類型的數據。
有些處理器支援多種尺寸的立即數,例如8位元或16位元,每一種指令形式採用獨特的操作碼和輔助記憶碼。如果一個程式設計師提供的數據值不適合,組譯器將會出現「超出範圍」的錯誤訊息。大多數組譯器允許一個立即數被表示為ASCII,十進制,十六進制,八進制或二進制數據。因此,ASCII字元'A'和65、0x41是一樣的。字串的位元組序在不同處理器之間可能不同,取決於組譯器和電腦架構。
參考資料
外部連結
Wikiwand in your browser!
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.