Next: Integer Range Overflow, Previous: Wraparound Arithmetic with Integers, Up: Integer Properties [Contents][Index]
Although unsigned integer arithmetic wraps around modulo a power of
two, signed integer arithmetic has undefined behavior on overflow in
C. Almost all modern computers use two’s complement signed
arithmetic that is well-defined to wrap around, but C compilers
routinely optimize based on the assumption that signed integer
overflow cannot occur, which means that a C program cannot easily get
at the underlying machine behavior. For example, the signed integer
expression (a + b < b) != (a < 0)
is not a reliable test for
whether a + b
overflows, because a compiler can assume that
signed overflow cannot occur and treat the entire expression as if it
were false.
These macros yield 1 if the corresponding C operators overflow, 0 otherwise. They work correctly on all known practical hosts, and do not rely on undefined behavior due to signed arithmetic overflow. They are integer constant expressions if their arguments are. They are typically easier to use than the integer range overflow macros (see Integer Range Overflow), and they support more operations and evaluation contexts than the integer overflow checking macros (see Checking Integer Overflow) or the wraparound macros (see Wraparound Arithmetic with Integers).
These macros can be tricky to use with arguments narrower than
int
. For example, in the common case with 16-bit short
int
and 32-bit int
, if a
and b
are of type
short int
then INT_MULTIPLY_OVERFLOW (a, b)
always
yields 0, as a * b
cannot overflow due to C’s rule that
a
and b
are widened to int
before multiplying.
For this reason, often it is better to use the integer overflow
checking macros (see Checking Integer Overflow) or the wraparound
macros (see Wraparound Arithmetic with Integers) when checking for overflow in
addition, subtraction, or multiplication.
Example usage:
#include <intprops.h> #include <limits.h> #include <stdio.h> /* Print A * B if in range, an overflow indicator otherwise. */ void print_product (long int a, long int b) { if (INT_MULTIPLY_OVERFLOW (a, b)) printf ("multiply would overflow"); else printf ("product is %ld", a * b); } /* Does the product of two ints always fit in a long int? */ enum { INT_PRODUCTS_FIT_IN_LONG = ! (INT_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN)) };
These macros have the following restrictions:
These macros are tuned for their last argument being a constant.
INT_ADD_OVERFLOW (a, b)
¶Yield 1 if a + b
would overflow, 0 otherwise. See above for
restrictions.
INT_SUBTRACT_OVERFLOW (a, b)
¶Yield 1 if a - b
would overflow, 0 otherwise. See above for
restrictions.
INT_NEGATE_OVERFLOW (a)
¶Yields 1 if -a
would overflow, 0 otherwise.
See above for restrictions.
INT_MULTIPLY_OVERFLOW (a, b)
¶Yield 1 if a * b
would overflow, 0 otherwise. See above for
restrictions.
INT_DIVIDE_OVERFLOW (a, b)
¶Yield 1 if a / b
would overflow, 0 otherwise. See above for
restrictions. Division overflow can happen on two’s complement hosts
when dividing the most negative integer by -1. This macro does
not check for division by zero.
INT_REMAINDER_OVERFLOW (a, b)
¶Yield 1 if a % b
would overflow, 0 otherwise. See above for
restrictions. Remainder overflow can happen on two’s complement hosts
when dividing the most negative integer by -1; although the
mathematical result is always 0, in practice some implementations
trap, so this counts as an overflow. This macro does not check for
division by zero.
INT_LEFT_SHIFT_OVERFLOW (a, b)
¶Yield 1 if a << b
would overflow, 0 otherwise. See above for
restrictions. The C standard says that behavior is undefined for
shifts unless 0≤b<w where w is a’s word
width, and that when a is negative then a <<
b
has undefined behavior, but this macro does not check these
other restrictions.
Next: Integer Range Overflow, Previous: Wraparound Arithmetic with Integers, Up: Integer Properties [Contents][Index]