標準Cでは `(i)= 1`は違法ですか?


8

私はこの標準に従っているCコンパイラを書いており、次のようなステートメントを解析した場合:

int i;
(i) = 1;

私のコンパイラ(i)は、それが右辺値であり、割り当て可能であってはならないことを指摘するエラーを報告します。

コードとルールを確認したところ、次のことがわかりました:代入式のセマンティクス:

代入演算子は、左オペランドとして変更可能な左辺値を持つものとします。

割り当て式は、割り当て後に左のオペランドの値を持っていますが、左辺値ではありません。

私の場合は、2つの代入式があります (i) = 1し、i括弧インチ したがって、これは(i)右辺値である必要があります。

だから私の質問です:(i) = 1このC標準では 違法ですか?


1
それはまだ左辺値であり、ラッピング括弧はそれを変更しません。
ジェフメルカド

1
みなさん、こんにちは。それが合法であるなら、標準のどの規則を指摘してください。私のコンパイラは規則を厳密に守っています。
ravenisadesk

i括弧内は代入式ではありません。割り当て式は、「割り当てに含まれる式」など、(i)適格なものを意味しません。割り当て式は割り当てです。
user2357112はモニカ

@ user2357112 iは割り当て式です。AST ツリーはEXPRESSION-> ASSIGNMENT_EXPRESSION-> CONDITIONAL_EXPRESSION-> LOGICAL_OR_EXPRESSION-> CAST_EXPRESSION-> UNARY_EXPRESSION-> POSTFIX_EXPRESSION-> PRIMARY_EXPRESSION-> IDENTIFIER
ravenisadesk

@reavenisadesk:assignment-expression非終端の文法は代入式と同じではありません。おおまかに言うassignment-expressionと、代入式または優先順位の高いものです。
user2357112は、

回答:


8

n1570(公開前の最後のC11標準ドラフト)を引用するには:

6.5.1一次表現(強調は私のもの)

5 括弧で囲まれた式は1次式です。そのタイプと値は、括弧なしの式と同じです。括弧なしの式がそれぞれ左辺値、関数指定子、またはvoid式である場合、それは左辺値、関数指定子、またはvoid式です。

iは左辺値なので、上記のとおりです(i)。そして、あなたの質問に答えるために、表現(i) = 1は有効なCです。


私はの括弧一次式のBNFを見てみましょう、問題を得た:( expression )、型と値が同じになるようにexpression、とexpressionあるassignment expression、とassignment expressionされprimary expression、単に、i扱いとなりassignment expression、それはのルールに従う必要がありますので、最後のassignment expression時を最後に、それはrvalueであるべきだと思います。
ravenisadesk

1
@reavenisadesk-それを除いて、白地に黒は右辺値ではありません。それともi = 1無効だと言っていますか?
StoryTeller-Unslander Monica

私が考えるi = 1これのために有効ですassignment-expression: unary-expression assignment-operator assignment-expression、場合にはi = 1、私は次のように扱われるunary-expression左辺値である、ではないassignment expression、私はあなただと思うi = 1の例では、そうではありません。
ravenisadesk

2
@reavenisadesk:文法は、左辺値または右辺値が何であるかを述べていません。セマンティクスはそうです。割り当て式の場合、C 6.5.16 3(「セマンティクス」の見出しのすぐ下)は割り当て式(これは、代入演算子で形成された式を説明する句であり、代入文ではなく、文法のトークンです) )は左辺値ではありません。それは言っていない代入式の文法トークンは左辺値ではありません。
Eric Postpischil

1
@reavenisadesk-エリックは私よりもはるかに雄弁にそれを説明しました。さらに、(i)ここでは不当に選択しているようです。セマンティクスに関する同じ点があらゆる種類の式に当てはまります。
StoryTeller-Unslander Monica

0

StoryTellerは、あなたの例で、式(i)がまだ左辺値である理由を標準ですでに説明しましたが、私はあなたが仕様にこだわっているのには理由がないと思うので、私があなたの懸念に取り組みましょう。

コードとルールを確認したところ、次のことがわかりました:代入式のセマンティクス:

代入演算子は、左オペランドとして変更可能な左辺値を持つものとします。

割り当て式は、割り当て後に左のオペランドの値を持っていますが、左辺値ではありません。

引用全体は、lhsやrhsではなく、割り当て式全体を指します。

「割り当て演算子は、その左オペランドとして変更可能な左辺値を持つものとします。」lhsは変更可能な左辺値でなければならないことを示しています。

「割り当て式は、割り当て後に左のオペランドの値を持っていますが、左辺値ではありません。」結果として、割り当て式全体がlhsの値を持ち、それ自体が右辺値であると述べています。

したがって、次のことがすべて当てはまります。

int i;
  i <- modifiable lvalue

(i) = 1;
  (i) <- modifiable lvalue (per StoryTeller's answer)
  1 <- rvalue
  ((i) = 1) <- rvalue

なぜこれが重要なのですか?以下を検討してください。

int i = 0, j = 0, k = 0;
i = j = k = 1;
// parsed as `i = (j = (k = 1))`
// the expression `k = 1` has the value `1` and is an rvalue
// the expression `j = (k = 1)` has the value `1` and is an rvalue

(i = 2) = 3;
// is invalid, the expression `i = 2` is an rvalue, but it may not be the lhs of the assignment

私の場合は、2つの代入式があります(i) = 1し、i括弧インチ したがって、これは(i)右辺値である必要があります。

いいえ、それは間違いです。(i) = 1唯一の代入式です。2つの部分式があります(1つの括弧で囲まれた識別子(i)と数値定数1)。


0

この答えは、@ Eric Postpischilに触発されました。

の生産assignment-expressionは:

<assignment-expression> ::= <conditional-expression>
                          | <unary-expression> <assignment-operator> <assignment-expression>

標準では、assignment expression特定とは代入演算子を使用した式を意味します。そう:

<conditional-expression> is not an assignment expression
<unary-expression> <assignment-operator> <assignment-expression> is an assignment expresssion

だからルール:

割り当て式は、割り当て後に左のオペランドの値を持っていますが、左辺値ではありません。

生産<unary-expression> <assignment-operator> <assignment-expression>にのみ適合し、<conditional-expression>

この例(i) =1iは、はですが、ではあり<assignment-expression>ません。そのためassignment expression、それは<conditional-expression>lvauleで(i)あり、lvalueです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.