Next: , Previous: , Up: Integer Properties   [Contents][Index]


17.7.5 Integer Type Overflow

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]