2011-03-14 5 views
0

この質問は前のproblemに関連しています。私が得た答えは"これは未定義の動作です。"(-i == i ++)は未定義の動作ですか?

誰が説明してください:

  • 未定義の動作とは何ですか?
  • 私のコードが未定義の動作をしていることを知る方法はありますか?

例コード:

int i = 5; 
if (--i == i++)   
    Console.WriteLine("equal and i=" + i);   
else 
    Console.WriteLine("not equal and i=" + i); 

//output: equal and i=6 
+0

あなたはどの言語で作業していますか? C#とCは非常に異なっています – Cameron

+3

Uh、CまたはC#?これは有効ではありませんC、なぜあなたはタグを追加しましたか? – GManNickG

+0

"未定義の動作とは何ですか?"その近くに重力と発電所に応じて3または428,3。 – stefan

答えて

2

未定義の行動は何ですか?

これは、適切な言語仕様で特に定義されていない動作です。一部の仕様では、明示的に未定義のものが挙げられますが、実際に定義されていないものは定義されていません。

どのように私のコードが未定義の動作をしていることが分かりますか?

うまくいけば、あなたのコンパイラが警告を表示します - それは場合でなければ、あなたは言語仕様を読んで、これらの種類の問題を引き起こすすべての面白いコーナーケースと隅&割れ目について学ぶ必要があります。

注意してください!

1

はい、その式も(CおよびC++では)未定義の動作です。ルールの詳細については、http://en.wikipedia.org/wiki/Sequence_pointを参照してください。より一般的に(つまり、コードが違反する一連のルール)「シーケンスポイント」を検索することもできます。

0

C標準ではそう言います。そしてあなたの例は明確に未定義の行動を示しています。

評価の順序によっては、比較は4 == 5または5 == 6である必要があります。しかし、条件はTrueを返します。

3

これは、Cで未定義ますが、C#で明確に定義されています:

C#(ECMA-334)の仕様 "演算子の優先順位と結合" セクション(§14.2.1)から:

  • 代入演算子とヌル合体演算子を除いて、すべての バイナリ演算子は、 アソシエイティブのままです。これは、演算 が左から右へ実行されることを意味します。 [例:x + y + zは(x + y)+ zとして評価されます。端例]
--i

だからがi++そして4にiを変更、最初に評価及び4に評価され、評価5にiを変更するが、4に評価されます。

+0

その声明はどこにありますか? CまたはC#? –

+2

それはそれが定義されていることは間違いありませんが、それは定義された場所や方法ではありません。これは割り当ても条件付きの操作でもありません。 – Guffa

+0

@Guffa、ありがとうございました。 –

0

あなたの前の質問には、[C]タグ付けされたので、私はあなたの現在の問題のコードは(C.

C99における未定義の動作の定義が言うようには見えませんが、Cに基づいて答えています§3.4.3):この国際規格は

2 NOTE可能な未定義の動作が無視の範囲何の要件を課さない そのため移植性や、誤ったプログラム構築物の使用時や、誤ったデータの
1未定義の動作
行動、 behaへの予測不可能な結果との完全な状況(診断メッセージの発行の有無にかかわらず)環境の特徴としての文書化された方法での翻訳またはプログラム実行中に、翻訳または実行を終了すること(診断メッセージの発行を伴って)。

C標準の付録J.2には、定義されていない動作のリスト(長さ - 数ページ)がありますが、それでもまだ網羅的ではありません。ほとんどの場合、定義されていない動作はルールを破ったことを意味するため、ルールを知ることです。

0

未定義の動作=結果は、まったく同じ条件で実行したときに必ず同じになることは保証されません。また、異なるコンパイラまたはランタイムを使用して実行するときは常に同じ結果が保証されません。コードで

、それはオペランドの側が最初に実行されなければならないが指定されていない同等の比較演算子を使用しているので、--iまたはi++まず実行終わる可能性、および回答は、実際の実装に依存するであろうコンパイラの。最初に--iを実行すると、4 == 4、i = 5となります。最初にi++が実装されている場合は、5 == 5、i = 5となります。

答えが同じである可能性があるという事実は、コンパイラがこれが未定義の操作であることを警告するのを妨げません。

これが左手側(または右手側)を常に最初に実行することを定義する言語であれば、その動作は未定義ではなくなります。

1

(これは、CまたはC++を前提としています。)

カールの答えは、一般的に正確です。

特に、エレミアが指摘した問題は、sequence pointsです。

明確にするために、コードのチャンク( - i == ++ i)は1つの "起こっている"ものです。これは一度に評価されるコードの塊です。最初に起こることの定義された順序はありません。左辺が最初に評価されるか、右辺が比較されるか、あるいは等価が比較される可能性があります。次にiが増分されてから減分されます。これらのビヘイビアによって、この式の結果が異なる可能性があります。ここで何が起こるのかは「未定義」です。あなたは答えが何であるか分かりません。

これを文i = i + 1と比較してください。ここでは、右側が常に最初に評価され、その結果がiに格納されます。これは明確に定義されています。あいまいさはありません。

ほんの少し役に立ちます。

1

Cでは結果は未定義です。C#で定義されています。

Cでは、比較は次のように解釈されます。

は、任意の順序で、これらのすべての操作を行います。
を - Xにiの値を取得
そして、iを下げる - Yにiの値を取得し、その後、増分i
次に、xとyを比較します。 C#の

がより操作境界があるので、比較は次のように解釈される:i
次にXにiの値を取得
次いでY
iの値を取得し、次いでi
増加

増減xとyを比較する。

操作が操作境界内で実行される順序を選択するのはコンパイラによって異なります。したがって、矛盾する操作を同じ境界内に置くと、結果は不定になります。

関連する問題