8

テスト (c/cpp)

#include <stdio.h>

int main(int argc, char** argv)
{
  int a = 0, b = 0;
  printf("a = %d, b = %d\n", a, b);
  b = (++a)--;
  printf("a = %d, b = %d\n", a, b);

  return 0;
}

上記を .cpp ファイルとして保存すると、実行時にコンパイルされて出力されます。

a = 0, b = 0
a = 0, b = 1

ただし、.c ファイルとして保存すると、次のエラーが発生します。

test.c:7:12: error: lvalue required as decrement operator.

(++a)操作は操作の前に解決されるべきではありません(newValue)--か? 誰かがこれについて何か洞察を持っていますか?

4

4 に答える 4

14

C では、前置および後置のインクリメント/デクリメント演算子の結果は左辺値ではありません。

C++ では、後置インクリメント/デクリメント演算子の結果も左辺値ではありませんが、前置インクリメント/デクリメント演算子の結果は左辺値です。

(++a)--2 つのシーケンス ポイント間でオブジェクト値を 2 回変更しているため、C++ でのような処理は未定義の動作です。

編集: @bames53 コメントのフォローアップ。C++98/C++03 では未定義の動作ですが、C++11 でのシーケンス ポイントの考え方の変更により、この式が定義されるようになりました。

于 2013-02-10T14:55:15.163 に答える
3

C および C++ では、演算子の左側で使用できる左辺値式と使用=できない右辺値式があります。C++ では、参照セマンティクスがサポートされているため、より多くのものを左辺値にすることができます。

++ a = 3; /* makes sense in C++ but not in C. */

インクリメント演算子とデクリメント演算子は、引数を変更するため、代入に似ています。

C++03 では、(++a)--互いに順序付けられていない 2 つの操作が同じ変数を変更しているため、未定義の動作が発生します。,(一方が「前」で、もう一方が「後」であっても、&&、 、 などがないため、順序付けされていません?。)

C++11 では、式は期待どおりの動作をするようになりました。しかし、C11 はそのようなルールを変更しません。これは構文エラーです。

于 2013-02-10T14:58:09.393 に答える
2

標準に記載されている違いの正確な詳細を知りたい人のために、C99、§6.5.3/2 は次のように述べています。

前置 ++ 演算子のオペランドの値がインクリメントされます。結果は、インクリメント後のオペランドの新しい 値です。

対照的に、C++11、§5.3.2/1 は次のように述べています。

結果は更新されたオペランドです。それは左辺値であり、オペランドがビットフィールドの場合はビットフィールドです。

[どちらの場合も強調を追加]

また、が である場合(++a)--(少なくとも C++03 では) は未定義の動作をしますが、 がユーザー定義型の場合aは、独自のオーバーロードを使用しているため、およびの動作が定義されることに注意してください。 、次と同等のものを取得しています:inta++--

a.operator++().operator--(0);

各演算子は関数呼び出し (オーバーラップできません) になるため、実際に、定義済みの動作を強制するシーケンス ポイントがあります (この場合、動作が実際に定義されていることに注意してください)。

于 2013-02-10T15:04:34.787 に答える
0

§5.2.7 インクリメントとデクリメント:

後置式++の値は、そのオペランドの値です。[...]  オペランドは変更可能な左辺値でなければなりません

C コンパイルで発生するエラーは、これが C++ にのみ存在する機能であることを示唆するのに役立ちます。

于 2013-02-10T15:02:58.143 に答える