命令型プログラミングのシーケンスポイントは、以前の評価のすべての副作用が実行され、後続の評価からの副作用がまだ実行されていないことが保証される、コンピュータープログラムの実行の任意のポイントを定義します。
これは何を意味するのでしょうか?簡単な言葉で説明してもらえますか?
命令型プログラミングのシーケンスポイントは、以前の評価のすべての副作用が実行され、後続の評価からの副作用がまだ実行されていないことが保証される、コンピュータープログラムの実行の任意のポイントを定義します。
これは何を意味するのでしょうか?簡単な言葉で説明してもらえますか?
シーケンス ポイントが発生すると、基本的には、以前のすべての操作が完了したことが保証されることを意味します。
シーケンス ポイントを介在させずに変数を 2 回変更することは、未定義の動作の一例です。
たとえば、i = i++;
への 2 つの変更の間にシーケンス ポイントがないため、 は未定義ですi
。
問題を引き起こす可能性があるのは、変数を 2 回変更するだけではないことに注意してください。実際には、他の用途に関連する変更です。標準では、物事がどのように順序付けられるかについて議論する際に、「値の計算と副作用」という用語を使用します。たとえば、式
a = i + i++
では、i
(値の計算) とi++
(副作用) を任意の順序で実行できます。
ウィキペディアには、C および C++ 標準のシーケンス ポイントのリストがありますが、最終的なリストは常に ISO 標準から取得する必要があります。C11付録Cから(言い換え):
以下は、標準で説明されているシーケンス ポイントです。
&&
、||
、および,
;の第 1 オペランドと第 2 オペランドの評価の間。?:
演算子の最初のオペランドの評価と、2 番目と 3 番目のオペランドの評価の間。if
またはswitch
) の制御式。while
or do ステートメントの制御式。for
ステートメントの各式。シーケンス ポイントについて注意すべき重要な点は、シーケンス ポイントはグローバルではなく、一連のローカルな制約と見なす必要があるということです。たとえば、声明では
a = f1(x++) + f2(y++);
x++ の評価と f1 の呼び出しの間にシーケンス ポイントがあり、y++ の評価と f2 の呼び出しの間に別のシーケンス ポイントがあります。ただし、f2 が呼び出される前または後に x がインクリメントされるかどうか、また x が呼び出される前または後に y がインクリメントされるかどうかについての保証はありません。f1 が y を変更するか、f2 が x を変更する場合、結果は未定義になります (たとえば、コンパイラが生成したコードが x と y を読み取り、x をインクリメントし、f1 を呼び出し、以前に読み取った値に対して y をチェックし、さらに --if Barney のビデオと商品をすべて探し出して破壊する暴れ回る; 残念ながら、実際にそれを行うコードを生成する実際のコンパイラはないと思いますが、標準では許可されています)。
例を使用して paxdiablo の回答を拡張します。
ステートメントを仮定します
x = i++ * ++j;
3 つの副作用があります: i * (j+1)
x への結果の代入、i への 1 の加算、および j への 1 の加算です。副作用が適用される順序は指定されていません。i と j は、評価された直後にそれぞれインクリメントされるか、両方が評価されてから x が割り当てられるまでインクリメントされないか、または x が割り当てられるまでインクリメントされません。
シーケンス ポイントは、適用された順序に関係なく、すべての副作用が適用された (x、i、および j がすべて更新された) ポイントです。
これは、コンパイラがファンキーな最適化、トリック、マジックを実行する可能性があることを意味しますが、これらのいわゆるシーケンス ポイントで明確に定義された状態に到達する必要があります。