両方の数値が同じ符号を持つ場合にのみオーバーフローが可能です。両方が正である場合、数学的にはA + B > LLONG_MAX
、またはそれと同等の場合は、B > LLONG_MAX - A
でオーバーフローします。右辺は負ではないので、後者の条件はすでにB > 0
を意味します。同様の議論では、否定的なケースについては、B
の符号を確認する必要はありません(Ben Voigtのおかげで、B
の符号チェックが不要であることを指摘しています)。次に、オーバーフローを検出するために
if (A > 0) {
return B > (LLONG_MAX - A);
}
if (A < 0) {
return B < (LLONG_MIN - A);
}
return false;
をチェックすることができます。これらの計算は、最初のチェックのためにオーバーフローすることはありません。
A + B
の結果の符号を確認すると、オーバーフローする整数計算のラップアラウンドセマンティクスが保証されます。しかし、符号付き整数のオーバーフローは未定義の動作であり、ラップアラウンドが実装された動作のCPUであっても、コンパイラは未定義の動作が発生しないと想定し、オーバーフローチェックを完全に削除します。したがって、この質問に対するコメントで示唆された小切手は非常に信頼性が低い。次のような
'場合((A <0 && B <0 && A+B> 0)||(A> 0 && B> 0 && A + B <0) ){/ * Overflow * /} 'AとBの両方に同じ記号がある場合、オーバーフローすることができます。もしそうで、A + Bに同じ符号がないなら、オーバーフローの問題があります。他のニュースでは、これは基本的には最速のメソッドです。一定の時間内に実行されるため、一度だけ追加します。 – FrankieTheKneeMan
回答として投稿する必要があります。ところで、 'A = B = 0x8000000000000000'、次に' A + B = 0'とコードが機能しないコーナーケースがあります:p – riv
@FrankieTheKneeMan整数オーバーフローは未定義の動作です。 – john