Value categories
C言語における各 式 (演算子とその引数、関数呼び出し、定数、変数名など)は、2つの独立した特性によって特徴づけられます: 型 と 値カテゴリ です。
すべての式は、3つの値カテゴリのいずれかに属します:lvalue、non-lvalue object (rvalue)、およびfunction designator。
目次 |
Lvalue式
Lvalue式は、 オブジェクト型 を持ち、 void 型以外のあらゆる式であり、潜在的に オブジェクト を指定します(評価時にlvalueが実際にオブジェクトを指定していない場合の動作は未定義です)。言い換えれば、lvalue式は オブジェクトの同一性 に評価されます。この値カテゴリの名称(「左辺値」)は歴史的なものであり、CPLプログラミング言語における代入演算子の左側オペランドとしてのlvalue式の使用を反映しています。
Lvalue式は以下の lvalueコンテキスト で使用できます:
- アドレス取得演算子の被演算子として (ただし、左辺値が アドレス取得演算子 ビットフィールド を指す場合、または register 宣言されている場合は除く)。
- 前置/後置 インクリメントおよびデクリメント演算子 の被演算子として。
- メンバアクセス (ドット)演算子の左側被演算子として。
- 代入および複合代入 演算子の左側被演算子として。
lvalue式が
sizeof
、
_Alignof
または上記の演算子以外の文脈で使用される場合、完全型の非配列lvalueは
lvalue変換
を受け、これはオブジェクトの値をその記憶場所からメモリ読み込みするモデルを表します。同様に、配列lvalueは
sizeof
、
_Alignof
、アドレス取得演算子、または文字列リテラルからの配列初期化以外の文脈で使用される場合
配列からポインタへの変換
を受けます。
const
/
volatile
/
restrict
修飾子および
atomic
型のセマンティクスは、左辺値にのみ適用されます(左辺値変換によって修飾子が除去され、アトミック性が失われます)。
以下の式は左辺値です:
- 識別子(関数名付き引数を含む)、ただしオブジェクトを指定するものとして宣言された場合に限る(関数や列挙定数ではない)
- 文字列リテラル
- (C99) 複合リテラル
- 括弧で囲まれた式(括弧なしの式が左辺値である場合)
- メンバアクセス(ドット)演算子の結果(左辺引数が左辺値である場合)
-
ポインタを介したメンバアクセス演算子
->の結果 -
間接参照(単項
*)演算子をオブジェクトへのポインタに適用した結果 -
添字演算子(
[])の結果
変更可能な左辺値式
変更可能な左辺値( modifiable lvalue )とは、完全な非配列型の左辺値式であって、 const 修飾されておらず、かつ構造体/共用体の場合には、再帰的に const 修飾されたメンバーを持たないものを指します。
変更可能な左辺値式のみがインクリメント/デクリメントの引数、および代入演算子と複合代入演算子の左辺引数として使用できます。
非左辺値オブジェクト式
非左値オブジェクト式は、オブジェクトを指定せず、オブジェクトの同一性や記憶域の位置を持たない値を表すオブジェクト型の式であり、 rvalues として知られています。非左値オブジェクト式のアドレスを取得することはできません。
以下の式は非左辺値オブジェクト式です:
- integer, character, and floating constants
- lvalueを返すと指定されていないすべての演算子、以下を含む
-
- 任意の関数呼び出し式
- 任意のキャスト式(注:似た形式の複合リテラルは左辺値です)
- 非左辺値の構造体/共用体に適用されたメンバアクセス演算子(ドット)、 f ( ) . x 、 ( x, s1 ) . a 、 ( s1 = s2 ) . m
- すべての算術、関係、論理、ビット単位演算子の結果
- インクリメントおよびデクリメント演算子の結果(注:前置形式はC++では左辺値です)
- 代入演算子の結果(注:C++ではこれも左辺値です)
- 条件演算子(注:第2オペランドと第3オペランドが同じ型の左辺値の場合、C++では左辺値です)
- コンマ演算子(注:第2オペランドが左辺値の場合、C++では左辺値です)
-
アドレス取得演算子、単項
*演算子の結果に適用されて無効化された場合でも
特別なケースとして、 void 型の式は、表現を持たず記憶域を必要としない値を生成する非左値オブジェクト式であると見なされます。
|
配列型のメンバー(ネストされた可能性あり)を持つ構造体/共用体の右辺値は、実際には 一時的な生存期間 を持つオブジェクトを指定することに注意してください。このオブジェクトは、配列メンバーのインデックス付けによって形成される左辺値式、または配列メンバーの配列からポインタへの変換によって得られたポインタを通じた間接参照によってアクセスできます。 |
(C99以降) |
関数指示子式
関数指示子(
関数宣言
によって導入される識別子)は、関数型の式です。アドレス取得演算子、
sizeof
、および
_Alignof
以外の文脈で使用される場合(後者2つは関数に適用されるとコンパイルエラーを生成します)、関数指示子は常に関数への非左値ポインタに変換されます。関数呼び出し演算子は関数へのポインタに対して定義されており、関数指示子自体に対してではないことに注意してください。
参考文献
- C23規格 (ISO/IEC 9899:2024):
-
- 6.3.2.1 左辺値、配列、および関数指示子 (p: 48-49)
- 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++ ドキュメント
for
Value categories
|