私はCで整数を使用していて、オーバーフローがいつどのように発生するかについてさらに調査しようとしていました。
2つの正の数を加算すると、その合計がオーバーフローすることに気づきました。常に負の数になります。
一方、2つの負の数を加算し、その合計がオーバーフローすると、常に正の数(0を含む)が得られます。
私はいくつかの実験をしましたが、これがすべての場合に当てはまるかどうか知りたいです。
整数オーバーフローは、C では未定義の動作です。
通常の算術変換後の結果が符号付き型であり、結果の型で表現できない場合、C は整数オーバーフローを含む式を言います。代入式とキャスト式は例外で、整数変換によって支配されます。
unsigned 型の式はオーバーフローできず、0U - 1
isのようにラップしUINT_MAX
ます。
例:
INT_MAX + 1 // integer overflow
UINT_MAX + 1 // no overflow, the resulting type is unsigned
(unsigned char) INT_MAX // no overflow, integer conversion occurs
整数式のオーバーフローを決してさせないでください。最新のコンパイラ ( などgcc
) は、未定義の動作である整数オーバーフローを利用して、さまざまな種類の最適化を実行します。
例えば:
a - 10 < 20
昇格後a
の型の場合、式は(最適化が有効になっている場合) に縮小されます。int
gcc
a < 30
a
が から の範囲INT_MIN + 10 - 1
にある場合、式が未定義の動作になることを利用しINT_MIN
ます。
が の場合、この最適化は実行できませんでした。これa
は、が のunsigned int
場合、 (未定義の動作なし)として評価する必要a
があるためです。に最適化すると、がである場合に必要な結果とは異なる結果になります。0
a - 10
UINT_MAX - 9
a - 10 < 20
a < 30
a
0
9
Overflow of signed integers is undefined behaviour in C, so there are no guarantees.
That said, wrap around, or arithmetic modulo 2N, where N
is the number of bits in the type, is a common behaviour. For that behaviour, indeed if a sum overflows, the result has the opposite sign of the operands.
Formally, the behaviour of signed arithmetic on overflow is undefined; anything can happen and it is 'correct'. This contrasts with unsigned arithmetic, where overflow is completely defined.
In practice, many older compilers used signed arithmetic which overflowed as you describe. However, modern GCC is making changes to the way it works, and you'd be very ill-advised to rely on the behaviour. It may change at any time when anything in the environment where your code is compiled changes — the compiler, the platform, ...