web-dev-qa-db-ja.com

C ++で動作するときに、複数のデクリメント演算子がCで動作しないのはなぜですか?

this の質問を見て、いくつかのコードを試します:

int x = 100;

while ( 0 <-------------------- x )
{
    printf("%d ", x);
}

gccでコンパイルしようとすると、次のエラーが発生しました。

file.c: In function 'main':
file:c:10:27: error: lvalue required as decrement operand
 while ( 0 <-------------------- x )

しかし、g++でコンパイルすることはできます。このコードがC++では有効だがCでは無効なのはなぜですか?

48
MD XF

Cでは、_--x_は値であり、左辺値ではありません。その効果は、xをデクリメントし、xの新しく割り当てられた値に評価することです。 _--x_は左辺値ではないため、デクリメントできません。

C++では、_--x_は右辺値ではなく左辺値です。その効果は、xをデクリメントし、左辺値としてxに評価することです。 _--x_は再び左辺値であるため、再びデクリメントできます。

_--x_がC++で左辺値であることが理にかなっている理由は、C++が参照型を導入したためです。与えられた

_void f(int &);
int i;
_

f(--i)を呼び出すと意味があります。これは、iをデクリメントした後に参照で渡します。

Cには参照型がないため、_--i_が左辺値であることにはほとんど意味がありません。歴史的には、C++とは異なり、Cはルールを変更する説得力のある理由を得ることはありませんでした。

C++では、実際に機能させるために_--x_を左辺値にするよりも大幅な変更が必要でした。 xへの変更と後続の左辺値から値への変換との間にシーケンスポイントがないため、_--x_を左辺値にすると、_--x_は未定義の動作になります。 _----x_の場合はさらに明確です。 C++は、シーケンスルールを変更して機能させる必要がありました。 Cでは、順序付け規則の変更により、既存のコンパイラが新しい規則に準拠するのに問題が発生する可能性があるため、大きなメリットがない限り、そのような変更は拒否される可能性があります。

90
user743382