1

乗算を評価するには、最初の項を評価し、次に 2 番目の項を評価し、最後に 2 つの値を乗算する必要があります。

0 で乗算されたすべての数値が 0 であることを考えると、最初の項の評価が 0 を返す場合、2 番目の項を評価せずに乗算全体が 0 に評価されると予想されます。

ただし、このコードを試すと:

var x = 0 * ComplexOperation();

x が 0 であることがわかっているにもかかわらず、関数 ComplexOperation が呼び出されます。

最適化された動作は、最初の項が true と評価された場合にのみ 2 番目の項を評価するブール演算子 '&&' とも一致します。(「&」演算子は、いずれの場合も両方の項を評価します)

でこの動作をテストしましC#たが、ほとんどすべての言語で同じだと思います。

4

4 に答える 4

15

まず、浮動小数点の場合、あなたの主張は真実ではありません! 0 * infは 0 ではなく、0 ではないと考えてください0 * nan

しかし、より一般的には、最適化について話している場合、コンパイラはComplexOperation、副作用がないことを証明できるかどうかを自由に評価しないと思います。

しかし、あなたは本当に短絡セマンティクス(つまり、コンパイラ機能ではなく言語機能) について話していると思います。もしそうなら、本当の正当性は、一貫性を維持するために、C# が以前の言語 (元は C) のセマンティクスをコピーしていることです。

于 2013-01-31T16:33:29.240 に答える
6

C# は関数型ではないため、関数には副作用が生じる可能性があります。たとえば、内部から何かを出力しComlpexOperationたり、グローバルな静的変数を変更したりできます。したがって、呼び出されるかどうかは*契約によって定義されます。

&とを使用したさまざまなコントラクトの例を見つけました&&

于 2013-01-31T16:37:51.263 に答える
3

言語は、短絡セマンティクスを持つ演算子と持たない演算子を定義します。関数ComplexOperationには副作用があり、それらの副作用は意図的である可能性があり、関数の結果が事実上使用されていないという理由だけで、コンパイラーはそれらが発生しないと自由に仮定できません。

于 2013-01-31T16:36:45.150 に答える
2

また、これは難読化された言語設計になると付け加えます。という趣旨のSOの質問がたくさんあります...

//why is foo only called 9 times?????????
for(int i = 0; i < 10; i++) {
    print((i-5)*foo());
}

ブール値の短絡を許可し、短絡を許可しないのはなぜ0*ですか? まず最初に、ショート サーキット ブール値と副作用を混在させることは、コードのバグの一般的な原因であると言います。プログラマーが 0 の整数の穴にまったく慣れていると想像してみてください。

于 2013-01-31T16:36:24.930 に答える