未定義の動作とシーケンスポイント

1000

「シーケンスポイント」とは何ですか?

未定義の振る舞いとシーケンスポイントの関係は何ですか?

a[++i] = i;気分を良くするために、のような面白くて複雑な表現をよく使います。なぜそれらの使用をやめるべきですか?

これを読んだ場合は、フォローアップの質問「未定義の振る舞いとリロードされシーケンスポイント」に必ずアクセスしてください。

(注:これは、StackOverflowのC ++ FAQへのエントリを意味します。このフォームでFAQを提供するというアイデアを批評したい場合は、これをすべて開始したメタへの投稿がそのための場所になります。その質問は、FAQのアイデアが最初に始まったC ++チャットルームで監視されているため、アイデアを思いついた人があなたの答えを読む可能性が非常に高くなります。)

5 answers

688
Prasoon Saurav 2010-11-14 19:39.

C ++ 98およびC ++ 03

この答えは、C ++標準の古いバージョンに対するものです。標準のC ++ 11およびC ++ 14バージョンには、正式には「シーケンスポイント」が含まれていません。代わりに、操作は「前にシーケンスされます」または「シーケンスされていない」または「不確定にシーケンスされます」。正味の効果は基本的に同じですが、用語が異なります。


免責事項:わかりました。この答えは少し長いです。それで、それを読んでいる間、忍耐を持ってください。あなたがすでにこれらのことを知っているならば、それらをもう一度読むことはあなたを夢中にさせることはありません。

前提条件:C ++標準の基本的な知識


シーケンスポイントとは何ですか?

標準は言う

シーケンスポイントと呼ばれる実行シーケンス内の特定の指定されたポイントで、前の評価のすべての副作用が完了し、後続の評価の副作用が発生していないものとします。(§1.9/ 7)

副作用?副作用とは何ですか?

式の評価は何かを生み出し、さらに実行環境の状態に変化があった場合、その式(その評価)には何らかの副作用があると言われています。

例えば:

int x = y++; //where y is also an int

初期化操作に加えて、演算子のy副作用によりの値が変更され++ます。

ここまでは順調ですね。シーケンスポイントに移ります。comp.lang.cの作者によって与えられたseq-pointsの交互の定義Steve Summit

シーケンスポイントは、ほこりが落ち着き、これまでに見られたすべての副作用が完了することが保証されている時点です。


C ++標準にリストされている一般的なシーケンスポイントは何ですか?

それらは:

  • 完全な式の評価の最後に(§1.9/16)(完全な式は、別の式の部分式ではない式です。)1

    例:

    int a = 5; // ; is a sequence point here
    
  • 最初の式の評価後の次の各式の評価(§1.9/182

    • a && b (§5.14)
    • a || b (§5.15)
    • a ? b : c (§5.16)
    • a , b (§5.18)(ここで、a、bはコンマ演算子です。inはコンマ演算子でfunc(a,a++) ,はなく、引数aとの間の単なる区切り文字a++です。したがって、その場合の動作は定義されていません(aプリミティブ型と見なされる場合))
  • 関数呼び出し時(関数がインラインであるかどうかに関係なく)、関数本体の式またはステートメントの実行前に行われるすべての関数引数(存在する場合)の評価後(§1.9/17)。

1:注:完全式の評価には、字句的に完全式の一部ではない部分式の評価を含めることができます。たとえば、デフォルトの引数式(8.3.6)の評価に関係する部分式は、デフォルトの引数を定義する式ではなく、関数を呼び出す式で作成されたと見なされます。

2:示されている演算子は、5項で説明されているように、組み込み演算子です。これらの演算子の1つが有効なコンテキストでオーバーロードされ(13節)、ユーザー定義の演算子関数を指定すると、式は関数呼び出しを指定し、オペランドは、それらの間に暗黙のシーケンスポイントがなくても、引数リストを形成します。


未定義の振る舞いとは何ですか?

標準セクションに未定義の動作を規定する§1.3.12ように

この国際規格が要件を課していない、誤ったプログラム構成または誤ったデータの使用時に発生する可能性があるような動作3

この国際規格が行動の明示的な定義の説明を省略している場合にも、未定義の行動が予想される可能性があります。

3:許容される未定義の動作は、予測できない結果で状況を完全に無視することから、環境に特徴的な文書化された方法で翻訳またはプログラムの実行中に動作すること(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了にまで及びます。 (診断メッセージの発行を伴う)。

要するに、未定義の振る舞いは、デーモンがあなたの鼻から飛び出し、あなたのガールフレンドが妊娠するまで、何でも起こり得ることを意味します。


未定義の振る舞いとシーケンスポイントの関係は何ですか?

その前に、未定義の振る舞い、未指定の振る舞い、および実装定義の振る舞いの違いを知っておく必要があります。

また、それを知っている必要がありthe order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecifiedます。

例えば:

int x = 5, y = 6;

int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.

ここに別の例があります。


今の標準は§5/4言う

  • 1)前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。

どういう意味ですか?

非公式には、2つのシーケンスポイント間で変数を複数回変更してはならないことを意味します。式ステートメントでは、next sequence pointは通常、終了セミコロンにあり、previous sequence pointは前のステートメントの終わりにあります。式に中間を含めることもできますsequence points

上記の文から、次の式は未定義の振る舞いを呼び出します。

i++ * ++i;   // UB, i is modified more than once btw two SPs
i = ++i;     // UB, same as above
++i = 2;     // UB, same as above
i = ++i + 1; // UB, same as above
++++++i;     // UB, parsed as (++(++(++i)))

i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)

ただし、次の式は問題ありません。

i = (i, ++i, 1) + 1; // well defined (AFAIK)
i = (++i, i++, i);   // well defined 
int j = i;
j = (++i, i++, j*i); // well defined

  • 2)さらに、前の値は、格納される値を決定するためにのみアクセスされるものとします。

どういう意味ですか?つまり、オブジェクトが完全な式内に書き込まれる場合、同じ式内のオブジェクトへのすべてのアクセスは、書き込まれる値の計算に直接関与する必要があります

たとえばi = i + 1i(LHSおよびRHSでの)すべてのアクセスは、書き込まれる値の計算直接関与します。だから大丈夫です。

このルールは、法的な表現を、アクセスが明らかに変更に先行する表現に効果的に制限します。

例1:

std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2

例2:

a[i] = i++ // or a[++i] = i or a[i++] = ++i etc

のアクセスのi1つ(の1つa[i])は、最終的にiに格納される値(で発生する)とは関係がないため、許可されi++ません。したがって、定義するための適切な方法はありません。コンパイラー-増分値が格納される前または後にアクセスを実行する必要があるかどうか。したがって、動作は定義されていません。

例3:

int x = i + i++ ;// Similar to above

ここでC ++ 11の回答をフォローアップします。

277
Prasoon Saurav 2010-11-16 01:12.

これは私の以前の回答のフォローアップであり、C ++ 11関連の資料が含まれています。


前提条件:関係(数学)の初歩的な知識。


C ++ 11にシーケンスポイントがないというのは本当ですか?

はい!これは非常に真実です。

C ++ 11では、シーケンスポイントSequenceedBeforeSequenceedAfter(およびUnsequencedIndeterminately Sequenced)の関係に置き換えられました。


この「前にシーケンスされた」ことは正確には何ですか?

前にシーケンス(§1.9/ 13)は次のような関係です。

  • 非対称
  • 推移的

単一のスレッドによって実行され、厳密な半順序を誘発する評価の間1

正式には、任意の2つの評価を与えられた意味(下記参照) AB、場合Aれる前に配列決定され B、その後の実行はA 先行するものの実行をB。もしA前に配列決定されていないBB前に配列決定されていないA場合、A及びBあるunsequenced 2

評価AとはBされている不定、配列決定のいずれかのときAの前に配列決定されBたりBする前に、配列決定されるAが、それは指定されていない3

[注]
1:厳密半順序である二項関係 "<"セット上Pでありasymmetric、そしてtransitive全てのために、すなわち、ab、及びcP:、我々は持っている
........(I)。a <bの場合¬(b <a)(asymmetry);
........(ii)。a <bおよびb <cの場合、a <c(transitivity)。
2:順序付けられていない評価の実行は重複する可能性があります。
3:不確定に順序付けられた評価重複できません、どちらかを最初に実行できます。


C ++ 11のコンテキストでの「評価」という言葉の意味は何ですか?

C ++ 11では、式(または部分式)の評価には一般に次のものが含まれます。

  • 値の計算(glvalue評価のためにオブジェクトのIDを決定し、prvalue評価のためにオブジェクトに以前に割り当てられた値をフェッチすることを含む)および

  • 副作用の開始。

今(§1.9/ 14)は言う:

完全な式に関連付けられたすべての値の計算と副作用は、評価される次の完全な式に関連付けられたすべての値の計算と副作用のシーケンスされます。

  • 簡単な例:

    int x; x = 10; ++x;

    に関連++xする値の計算と副作用は、の値の計算と副作用の後にシーケンスされます。x = 10;


ですから、未定義の振る舞いと上記のものとの間には何らかの関係があるはずですよね?

はい!正しい。

(§1.9/ 15)では、

特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は順序付けられていません4

例えば ​​:

int main()
{
     int num = 19 ;
     num = (num << 3) + (num >> 3);
} 
  1. 演算子のオペランドの評価は、+相互に関連して順序付けられていません。
  2. <<>>演算子のオペランドの評価は、相互に関連して順序付けられていません。

4:プログラムの実行中に複数回評価される式で、unsequenced及び不定配列決定し、その部分式の評価が異なる評価で一貫して行う必要はありません。

(§1.9/ 15)演算子のオペランドの値の計算は、演算子の結果の値の計算の前にシーケンスされます。

意味するx + yの値の計算xとはyの価値計算の前に配列決定されます(x + y)

さらに重要なことには

(§1.9/ 15)スカラーオブジェクトへの副作用がどちらかに対して順序付けられていない場合

(a)同じスカラーオブジェクトに対する別の副作用

または

(b)同じスカラーオブジェクトの値を使用した値の計算。

動作は未定義です。

例:

int i = 5, v[10] = { };
void  f(int,  int);
  1. i = i++ * ++i; // Undefined Behaviour
  2. i = ++i + i++; // Undefined Behaviour
  3. i = ++i + ++i; // Undefined Behaviour
  4. i = v[i++]; // Undefined Behaviour
  5. i = v[++i]: // Well-defined Behavior
  6. i = i++ + 1; // Undefined Behaviour
  7. i = ++i + 1; // Well-defined Behaviour
  8. ++++i; // Well-defined Behaviour
  9. f(i = -1, i = -1); // Undefined Behaviour (see below)

関数を呼び出すとき(関数がインラインであるかどうかに関係なく)、任意の引数式、または呼び出された関数を指定する後置式に関連付けられたすべての値の計算と副作用は、本体のすべての式またはステートメントの実行前にシーケンスされます。関数と呼ばれます。[注: 異なる引数式に関連する値の計算と副作用は順序付けられていません。—エンドノート]

(5)(7)および(8)未定義の動作を呼び出さないでください。詳細な説明については、次の回答を確認してください。

  • C ++ 0xの変数に対する複数のプリインクリメント操作
  • シーケンスされていない値の計算

最後の注意

投稿に欠陥を見つけた場合は、コメントを残してください。パワーユーザー(担当者> 20000)は、タイプミスやその他の間違いを修正するために、投稿を編集することを躊躇しないでください。

31
AlexD 2017-09-12 22:50.

C ++ 17N4659)には、式の評価のより厳密な順序を定義する、慣用的なC ++の式の評価順序の改良の提案が含まれています。

特に、次の文

8.18代入および複合代入演算子
...。

いずれの場合も、代入は、右オペランドと左オペランドの値計算の後、代入式の値計算の前に順序付けられます。右のオペランドは、左のオペランドの前にシーケンスされます。

次の説明と一緒に

Xに関連するすべての値の計算とすべての副作用が、式Yに関連するすべての値の計算とすべての副作用の前にシーケンスされる場合、式Xは式Yの前にシーケンスされると言われます。

問題のケースを含め、以前に定義されていない動作のいくつかのケースを有効にします。

a[++i] = i;

ただし、他のいくつかの同様のケースでは、未定義の動作が発生します。

N4140

i = i++ + 1; // the behavior is undefined

しかし、 N4659

i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined

もちろん、C ++ 17準拠のコンパイラを使用することは、必ずしもそのような式を書き始める必要があることを意味するわけではありません。

11
Yttrill 2010-12-08 09:44.

変更には根本的な理由があると思います。古い解釈を明確にするのは単なる見た目だけではありません。その理由は並行性です。精緻化の不特定の順序は、いくつかの可能なシリアル順序の1つを選択するだけです。これは、指定された順序がない場合、同時評価が可能であるため、順序の前後とはまったく異なります。古いルールではそうではありません。例:

f (a,b)

以前はa、b、またはb、aのいずれかでした。これで、aとbは、インターリーブされた命令または異なるコアでさえも評価できます。

2
awiebe 2018-10-26 17:40.

ではC99(ISO/IEC 9899:TC3)、これまでこの議論から欠席思われる以下のsteteentsはevaluaitonの順序について作られています。

[...]部分式の評価の順序と副作用が発生する順序はどちらも指定されていません。(セクション6.5 pp 67)

オペランドの評価の順序は指定されていません。代入演算子の結果を変更しようとしたり、次のシーケンスポイントの後でそれにアクセスしようとした場合、動作は定義されていません。(セクション6.5.16 pp 91)

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

2021 年 6 月 8 日にニューヨーク市で開催された covid-19 パンデミックで亡くなった人々の命を偲び、祝うために、ネーミング ザ ロスト メモリアルズが主催するイベントと行進の最中に、グリーンウッド墓地の正門から記念碑がぶら下がっています。週末、ジョー・バイデン大統領は、covid-19 パンデミックの終息を宣言しました。これは、過去 2 年以上にわたり、公の場でそうするための長い列の中で最新のものです。

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

オハイオ州のエミリー・デシャネル みんな早く来て、ボーンズが帰ってきた!まあ、ショーボーンズではなく、彼女を演じた俳優. エミリー・デシャネルに最後に会ってからしばらく経ちました.Emily Deschanel は、長期にわたるプロシージャルな Bones の Temperance “Bones” Brennan としてよく知られています。

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

どうやら、ドナルド・トランプに近い人々は、今月初めにFBIによって家宅捜索された彼のMar-a-Lago財産からの映像を公開するよう彼に勧めています. 前大統領はテープを公開するかどうかを確認していませんが、息子はフォックス・ニュースにそうなるだろうと語った.

Andor は、他の Star Wars ショーから大きな距離を置きます。

Andor は、他の Star Wars ショーから大きな距離を置きます。

アンドールの一場面。数十年前、ジョージ・ルーカスがスター・ウォーズのテレビ番組を制作するのを妨げた主な理由は、お金でした。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language