數值類別
C 語言中的每個運算式(包含運算子及其運算元、函式呼叫、常數、變數名稱等)都具有兩個獨立的屬性:類型與值類別。
每個運算式都屬於以下三種值類別之一:左值 (lvalue)、非左值物件 (rvalue) 以及函式指示項 (function designator)。
目錄 |
[編輯] 左值運算式
左值運算式是指任何類型為物件類型(非 void 類型)的運算式,且該運算式可能指定一個物件(若左值在求值時並未實際指定物件,則行為未定義)。換句話說,左值運算式會求值為「物件識別」。此值類別的名稱("left value")源自歷史,反映了在 CPL 程式語言中,左值運算式常被用作賦值運算子的左運算元。
左值運算式可用於以下「左值上下文」(lvalue contexts):
- 作為取址運算子的運算元(若該左值指定一個位元欄位或被宣告為 register 則例外)。
- 作為前置/後置遞增與遞減運算子的運算元。
- 作為成員存取(點運算子)的左運算元。
- 作為賦值與複合賦值運算子的左運算元。
若左值運算式被用於 sizeof、_Alignof 或上述運算子以外的任何上下文,則任何完整類型的非陣列左值都會進行左值轉換 (lvalue conversion),這模擬了從該物件所在位置載入值的記憶體存取。同樣地,當陣列左值被用於 sizeof、_Alignof、取址運算子或字串字面量陣列初始化以外的上下文時,會進行陣列至指標轉換 (array-to-pointer conversion)。
const/volatile/restrict 限定詞及原子類型的語義僅適用於左值(左值轉換會移除這些限定詞及原子性)。
以下運算式為左值:
- 識別項,包括函式參數,前提是它們被宣告為指定物件(而非函式或列舉常數)。
- 字串字面量。
- (C99) 複合字面量。
- 若括號內的運算式為左值,則括號運算式亦為左值。
- 若成員存取(點運算子)的左運算元為左值,則該運算結果亦為左值。
- 透過指標進行成員存取(
->運算子)的結果。 - 對指向物件的指標應用間接存取(一元
*)運算子的結果。 - 下標運算子 (
[]) 的結果。
[編輯] 可修改的左值運算式
「可修改的左值」是指任何完整、非陣列類型的左值運算式,且該運算式未被 const 限定,若為結構體或聯合體,其成員亦不得(遞迴地)被 const 限定。
僅可修改的左值運算式可用作遞增/遞減運算子的參數,以及賦值與複合賦值運算子的左運算元。
[編輯] 非左值物件運算式
被稱為「右值」(rvalues),非左值物件運算式是指那些不指定物件的物件類型運算式,它們僅代表沒有物件識別或儲存位置的值。無法對非左值物件運算式取址。
以下運算式為非左值物件運算式:
- 整數、字元與浮點數常數。
- 所有未規定返回左值的運算子,包括:
- 任何函式呼叫運算式。
- 任何轉型 (cast) 運算式(注意:看起來相似的複合字面量是左值)。
- 應用於非左值結構體/聯合體的成員存取運算子(點運算子),例如 f().x、(x,s1).a、(s1=s2).m。
- 所有算術、關係、邏輯與位元運算子的結果。
- 遞增與遞減運算子的結果(注意:C++ 中前置形式為左值)。
- 賦值運算子的結果(注意:C++ 中亦為左值)。
- 條件運算子(注意:若第二與第三運算元皆為同類型的左值,C++ 中其為左值)。
- 逗號運算子(注意:若第二運算元為左值,C++ 中其為左值)。
- 取址運算子的結果,即使應用於一元
*運算子的結果也一樣。
作為特殊情況,void 類型的運算式被視為不產生任何表示形式且無需儲存空間的非左值物件運算式。
請注意,若一個結構體/聯合體右值包含陣列類型的成員(可能是巢狀的),它實際上指定了一個具有暫存生命週期的物件。此物件可以透過對陣列成員進行索引,或對陣列成員進行陣列至指標轉換後解參考,所形成的左值運算式來存取。
[編輯] 函式指示項運算式
函式指示項(由函式宣告引入的識別項)是一種函式類型的運算式。當用於取址運算子、sizeof 與 _Alignof 以外的任何上下文時(後兩者對函式使用會導致編譯錯誤),函式指示項總是被轉換為非左值的函式指標。請注意,函式呼叫運算子是針對函式指標定義的,而非針對函式指示項本身。
[編輯] 參考資料
- C17 標準 (ISO/IEC 9899:2018)
- 6.3.2.1 左值、陣列與函式指示項 (p: 40)
- C11 標準 (ISO/IEC 9899:2011)
- 6.3.2.1 左值、陣列與函式指示項 (p: 54-55)
- C99 標準 (ISO/IEC 9899:1999)
- 6.3.2.1 左值、陣列與函式指示項 (p: 46)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.2.2.1 左值與函式指示項
[編輯] 參見
| C++ 文件 關於 值類別 (Value categories)
|