これは、加算演算の積分オーバーフロー「フラグ」を計算しています。これは、結果の大きさが。より小さいINT_MIN
か大きいかを表しINT_MAX
ます。これは、int
が32ビット、2の補数であり、符号付き数値の右シフトが上位ビットを複製する「算術」シフトであると想定しています。安全な想定はありません。
x
との符号がy
同じであるが、結果の符号が反対である場合、結果はオーバーフローしました。コンピューティングはこれですべてです。それほど複雑にする必要はありません。
加算によって整数例外が生成されず、不安定なパリティビットがないと仮定すると、この式は、元のコードと同じ精神で符号ビットを操作することによって機能します。
( x ^ y ) < 0 && ( x ^ result ) < 0 /* (A^B)<0 iff A and B have opposite sign */
明確に定義された動作に依存することに気を配りたい場合、結果がオーバーフローする可能性がある場合、実行x + y
は違法です。C規格に準拠したマシンは、このようなオーバーフロー(または自己破壊など)でプログラムを終了することが許可されているため、そもそもそれを回避する必要があります。
実行したいテストは
x + y > INT_MAX
x + y < INT_MIN
x
とy
直接の間に安全な操作はありません。方程式の一方を反対側に移動する必要があります。つまり、符号を逆にして減算を実行する必要があります。INT_MAX
から正の数を引くか、から負の数を引くのが安全なINT_MIN
ので、これらを変更できます。
y > INT_MAX - x
y < INT_MIN - x
それを行う最も安全な方法は、
x < 0? ( y < INT_MIN - x ) : ( y > INT_MAX - x );
編集:おっと、私は関数がオーバーフローフラグで何をしたかを推測しませんでした。明らかに、オーバーフローがない場合は結果を返しINT_MAX
、正のオーバーフローがある場合は戻りINT_MIN
、負のオーバーフローがある場合は戻ります。言い換えれば、それは飽和した追加です。これを行う方法は少し複雑で、作者は枝を取り除くのに苦労したようです。ただし、通常はオーバーフローは発生せず、予測可能な分岐は多くの演算よりも安価であるため、を使用してより簡単な実装を試す価値がありif … else
ます。