(++ i)++が有効なのに「++ i ++」が無効なのはなぜですか?


14

次のコードを考えてみましょう:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

次のエラーでコンパイルされます。

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

これは私には公平に聞こえます。後置インクリメントはコードのように解析されて、接頭増分よりも高い優先度を有するint b = ++(i++);i右辺値です。したがってエラー。

デフォルトの優先順位を上書きするために、括弧を付けたこのバリアントについて考えてみましょう。

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

このコードはコンパイルして3を返します。それ自体では、これは公平に聞こえますが、最初のコードとは矛盾しているようです。

質問:なぜ(++i)あるlvalueときiではないでしょうか?

ありがとう!

更新:上記のエラーメッセージはgcc(x86-64 9.2)からのものです。これが正確なレンダリングです: gccのエラー

Clang x86-64 9.0.0にはまったく異なるメッセージがあります: clangのエラー

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

GCCを使用すると、問題が後置演算子であるという印象を取得し、あなたはその後、ワンダことができる理由++iOKしばらくはi、したがって、私の質問ではありません。Clangを使用すると、問題が前置演算子にあることがより明確になります。


これは、もともとCでタグ付けされた、それは最も確かに有効なC.ではありません
アンティHaapala

本当にごめんなさい!動作はCでも同じだったと
思い

回答:


23

iおよび++iはどちらも左辺値i++ですが、右辺値です。

++(i++)接頭辞++i++右辺値であるに適用されているため、有効にできません。しかし、左辺値(++i)++なので問題++iありません。

Cでは状況が異なることに注意してください。i++++iどちらも右辺値です。(これは、CとC ++が同じルールを持っていると人々が考えるのをやめるべき理由の例です。人々はこれらの仮定を質問に挿入しますが、それは反駁されなければなりません。)


4

この宣言

int b = ++i++;

に相当

int b = ++( i++ );

後置インクリメント演算子は、インクリメント前のオペランドの値を返します。

C ++ 17標準から(8.2.6インクリメントとデクリメント)

1 postfix ++式の値は、そのオペランドの値です... 結果はprvalueです。

一方、単項インクリメント演算子は、インクリメント後にlvalueを返します。この宣言は

int b = (++i)++;

有効です。あなたは例えば書くことができます

int b = (++++++++i)++;

C ++ 17標準から(8.3.2インクリメントとデクリメント)

1接頭辞++のオペランドは、1を追加することによって変更されます。オペランドは、変更可能な左辺値でなければなりません。オペランドの型は、cv bool以外の算術型、または完全に定義されたオブジェクト型へのポインターでなければなりません。結果は更新されたオペランドです。これは左辺値であり、オペランドがビットフィールドである場合はビットフィールドです...

Cでは両方の演算子が左辺値ではなく値を返すことに注意してください。したがって、Cではこの宣言

int b = (++i)++;

無効です。


3

したがって、コードはint b = ++(i ++);として解析されます。そして、私は右辺値です。

いいえi。右辺値ではありません。i左辺値です。i++右辺値(具体的にはprvalue)。

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