そのため、今後のトピックを事前に確認しており、左辺値と右辺値に出くわしましたが、定義が混乱しています。なぜリテラルは左辺値なのですか?
「右辺値は、メモリ内のあるアドレスに格納されているデータ値を指します。右辺値は、値を割り当てることができない式です」
「左辺値の元の定義は、「割り当ての左側に表示できるオブジェクト」と呼ばれていました。ただし、const オブジェクトは左辺値ですが、割り当ての左側に表示することはできません。」
const
C には、オブジェクト、配列 (および const または配列のメンバーを持つオブジェクト)、不完全な型の式の 3 つの割り当て不可能な左辺値のカテゴリがあります。
文字列リテラルは配列です (つまり、文字列リテラル式が参照するオブジェクトは配列です)。それはそれらを左辺値にします。
非公式には、左辺値はオブジェクトを参照する式であり、文字列リテラルはオブジェクトです。
C で左辺値の正式な定義が必要な場合は、標準を参照してください。C99(6.3.2.1):
左辺値は、オブジェクト型または void 以外の不完全な型を持つ式です。左辺値が評価時にオブジェクトを指定しない場合、動作は未定義です。
脚注付き:
''lvalue'' という名前は、最初は代入式 E1 = E2 に由来します。ここで、左側のオペランド E1 は (変更可能な) 左辺値である必要があります。オブジェクトの「ロケーター値」を表していると考えた方がよいでしょう</p>
そのため、代入の LHS に現れることは、標準 C 以外の言語では左辺値が何か別の意味を持っていたという事実を除けば、それとは何の関係もありません。
その正式な定義により、整数定数も左辺値式である必要があると考えるかもしれません5
。これは式 (具体的には一次式) であり、オブジェクト型 (int
はオブジェクト型) を持ちます。式を評価することは確かに有効5
であるため、左辺値の場合は「オブジェクトを指定」する必要があります。
これは、オペランドがオブジェクトを指定する左辺値式である可能性があるというアドレス取得演算子の定義と矛盾します。コンパイラは を拒否し&5
、通常はそれが左辺値で5
はないというエラー メッセージを表示します。
答えは 6.5.1 にあると思います。これには、定数を含むさまざまなタイプのプライマリー式がリストされています。他の種類の primary-expression のそれぞれについて、それが左辺値である条件を示します。定数については、明らかに何も言わず、左辺値ではないことを示しています。しかし通常、C 標準では、"An X is..."という形式のテキスト ( Xをイタリック体で囲んだもの) は、X という用語の定義です。したがって、標準はより明確になると思います。
更新: n1570 (C11 の後期ドラフト) のテキストは、私の強調を追加すると、次のようになります。
左辺値は、潜在的にオブジェクトを指定する(void 以外のオブジェクト型を持つ) 式です。
そして、C89 (3.2.2.1) の同等のテキストには、「オブジェクトを指定する」と書かれています [hvd に感謝]。これは、標準の作成者もテキストに満足していないことを示唆しています。定数は潜在的にオブジェクトを指定しないため、この定義の下では数値定数は確かに左辺値ではありません。
左辺値の非公式な定義は、基本的に、オブジェクトの値を読み取ったり変更したりできるように、オブジェクト (C の意味ではメモリを消費するもの) を参照できる任意の式です。単項演算子を潜在的に適用できる&
ものはすべて左辺値です。
残念ながら、メモリ内のオブジェクトを参照できる式がいくつかありますが、セマンティクスは、その式を介してそのオブジェクトの値を変更できないようなものです。これには、配列式 (文字列リテラルを含む)、修飾された型のconst
式、および不完全な型の式が含まれます。
最後のタイプの例は、次のようなものです。
struct foo;
struct foo *fooptr;
式*fooptr
が不完全な型の式です。struct foo
まだ完全には定義されていません。
したがって、変更可能な左辺値と変更不可能な左辺値があります。変更可能な左辺値は、割り当てのターゲットになる場合があります。
文字列リテラルは、配列型の式であるため、変更不可能な左辺値です (文字列リテラルはchar
、メモリがプログラム全体から見えるように配列として格納され、プログラムの起動から終了まで保持されます。配列のセマンティクスは、配列式は代入の対象にならない場合があります)。これは、メモリ内の項目を参照しない 数値リテラルや個々の文字定数とは異なる状況です。
右辺値は、名前がないもの、またはアドレスを取得できないもの、または一時的なものとして定義されます。
最近では、元の定義は無効になっています。左辺値のアドレスを取得することはできますが、右辺値のアドレスを取得することはできません。これは、私にとって最も簡単な区別です。
あなたがそれのアドレスをとることができないならば、それは右辺値です。