Signed integer arithmetic has undefined behavior on overflow in C. Although almost all modern computers use two’s complement signed arithmetic that is well-defined to wrap around, C compilers routinely optimize assuming that signed integer overflow cannot occur, which means that a C program cannot easily get at the underlying machine arithmetic. For example:
if ((a + b < b) == (a < 0)) a += b; else printf ("overflow\n");
might not work as expected if a
and b
are signed,
because a compiler can assume that signed overflow cannot occur and
treat the entire if
expression as if it were true. And even if
a
is unsigned, the expression might not work as expected if
b
is negative or is wider than a
.
The following macros work around this problem by yielding an overflow
indication while computing the sum, difference, or product of two
integers. For example, if i
is of type int
,
INT_ADD_OK (INT_MAX - 1, 1, &i)
sets i
to
INT_MAX
and yields 1, whereas INT_ADD_OK (INT_MAX, 1,
&i)
yields 0.
Example usage:
#include <intprops.h> #include <stdio.h> /* Compute A * B, reporting whether overflow occurred. */ void print_product (long int a, long int b) { long int r; if (INT_MULTIPLY_OK (a, b, &r)) printf ("result is %ld\n", r); else printf ("overflow\n"); }
These macros work for both signed and unsigned integers, so they can
be used with integer types like time_t
that may or may not be
signed, depending on the platform.
These macros have the following restrictions:
INT_ADD_OK (a, b, r)
¶Compute the sum of a and b. If it fits into
*r
, store it there and yield 1. Otherwise yield
0, possibly modifying *r
to an unspecified value.
See above for restrictions.
INT_SUBTRACT_OK (a, b, r)
¶Compute the difference between a and b. If it fits into
*r
, store it there and yield 1. Otherwise yield
0, possibly modifying *r
to an unspecified value.
See above for restrictions.
INT_MULTIPLY_OK (a, b, r)
¶Compute the product of a and b. If it fits into
*r
, store it there and yield 1. Otherwise yield
0, possibly modifying *r
to an unspecified value.
See above for restrictions.
Other macros are available if you need wrapped-around results when overflow occurs (see Wraparound Arithmetic with Integers), or if you need to check for overflow in operations other than addition, subtraction, and multiplication (see Integer Type Overflow).