Next: Wraparound Arithmetic with Integers, Previous: Integer Bounds, Up: Integer Properties [Contents][Index]
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).
Next: Wraparound Arithmetic with Integers, Previous: Integer Bounds, Up: Integer Properties [Contents][Index]