13

プロジェクトでCoverityPreventを使用してエラーを見つけています。

この式のエラーを報告します(もちろん変数名は変更されます):

x=
   (a>= b) ?
   ++x: 0;

メッセージは次のとおりです。

EVALUATION_ORDERの欠陥:「x=(a>= b) ? ++x: 0;」では、「x」は「x」(割り当てLHS)で記述され、「(a>= b) ? ++x: 0;」で記述されますが、介在するシーケンスポイントがないため、副作用が発生する順序は定義されていません。メッセージの終わり

x = x++」は未定義ですが、これは少し難しいです。これは誤検知ですか?

4

6 に答える 6

29

条件演算子?:には、条件 (最初のオペランド) の評価と 2 番目または 3 番目のオペランドの評価の間にシーケンス ポイントがありますが、2 番目または 3番目のオペランドの評価の後には専用のシーケンス ポイントがありません。これは、この例の の 2 つの変更がx競合する可能性があることを意味します (シーケンス ポイントで区切られていません)。したがって、Coverity Prevent は正しいです。

その点に関するあなたの声明は、実質的には

a >= b ? x = ++x : x = 0;

と同じ問題がありx = ++xます。

x = ++xさて、あなたの質問のタイトルは、未定義かどうかわからないことを示唆しているようです。それは確かに未定義です。定義されていないのとまったく同じ理由で、定義されていませんx = x++。つまり、隣接するシーケンス ポイントのペア間で同じオブジェクトが複数回変更された場合、動作は未定義です。この場合x、割り当てによって変更され++、これらの変更を互いに「分離」するシーケンスポイントはありません。したがって、動作は未定義です。++xこの点でとの間にはまったく違いはありませんx++

于 2010-09-01T14:53:13.547 に答える
12

メッセージの正確さに関係なく、問題のコードを に置き換えると、x= (a>= b) ? x+1: 0;混乱することなく同じ結果が得られます。ツールが混乱している場合、このコードを次に見る人も混乱する可能性があります。

これはx、ここで依存する副作用のあるオーバーロードされたインクリメント演算子がないことを前提としています。

于 2010-09-01T14:53:16.067 に答える
8

このステートメントは、シーケンス ポイントに到達する前にx = ++x;変数に 2 回書き込みを行うため、動作は未定義です。x

于 2010-09-01T14:53:32.750 に答える
3

「x = ++x;」のコードを生成するコンパイラを想像するのは難しいです。実際には、「++x」と同じようには機能しません。ただし、x が揮発性でない場合、コンパイラがステートメント「y = ++x;」を処理することは正当です。なので

  y=x+1;
  x=x+1;

ステートメント「x = ++x;」したがって、

  x=x+1;
  x=x+1;

1 つの算術代入式の宛先が別のソース オペランドとしてあまりにも早く使用されると、パイプラインの遅延が発生する場合、前者の最適化が合理的である可能性があります。インクリメントされた変数と割り当てられた変数がまったく同じである場合、明らかに悲惨です。

変数「x」が揮発性である場合、意図的に意地悪をしようとしていないコンパイラーが「x = x++;」と正当に見なすことができるコードシーケンスは考えられません。'x' のすべての部分を正確に 1 回読み取り、'x' のすべての部分に同じ正しい値を正確に 2 回書き込む以外の効果があるためです。

于 2010-09-01T16:30:25.577 に答える
0

これを理解するには、シーケンス ポイントの基本を理解する必要があります。このリンクを参照してください: http://en.wikipedia.org/wiki/Sequence_point

= 演算子にはシーケンス ポイントがないため、x に再度割り当てられる前に x の値が変更されるという保証はありません。

于 2012-03-06T05:34:53.207 に答える
0

論理的には、「x=++x」または「x=x++」のいずれかを記述した場合、どちらの方法でも、最終結果は x が最初よりも 1 つ大きいと予想されると思います。しかし、それを少しだけ複雑にしてください。「x=x+(++x)」と書いたら?これは "x=x+(x+1)" と同じですか? それとも、最初に 1 を追加してから、それ自体に x を追加しますか。つまり、"x=(x+1)+(x+1)" ですか? "x=(x--)+(x++)" と書いたらどうなるでしょうか?

この種の構成要素に明確な意味を与える言語仕様を記述でき、それをきれいに実装できたとしても、なぜそうしたいのでしょうか? 同じ変数への割り当てに単項インクリメントを入れることはまったく意味がありません。無理に意味をなくしたとしても、有用な機能は提供されません。たとえば、"x+1=y-1" のような式を取り、それが本当に "x=y-2" を意味することを理解するコンパイラを書くことはできると思いますが、なぜわざわざする必要があるのでしょうか? ゲインはありません。

「x=x++-++x」で予測可能なことを行うコンパイラーを作成したとしても、プログラマーはルールを知って理解する必要があります。明らかなメリットがなければ、目的もなくプログラムが複雑になるだけです。

于 2010-09-01T17:05:55.170 に答える