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


17.7.4 Wraparound Arithmetic with Integers

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, on a typical machine with 32-bit two’s complement int the expression INT_MAX + 1 does not necessarily yield INT_MIN, because the compiler may do calculations with a 64-bit register, or may generate code that traps on signed integer overflow.

The following macros work around this problem by storing the wraparound value, i.e., the low-order bits of the correct answer, and by yielding an overflow indication. For example, if i is of type int, INT_ADD_WRAPV (INT_MAX, 1, &i) sets i to INT_MIN and yields 1 on a two’s complement machine. See Integer Type Overflow.

Example usage:

#include <intprops.h>
#include <stdio.h>

/* Print the low order bits of A * B,
   reporting whether overflow occurred.  */
void
print_product (long int a, long int b)
{
  long int r;
  int overflow = INT_MULTIPLY_WRAPV (a, b, &r);
  printf ("result is %ld (%s)\n", r,
          (overflow
           ? "after overflow"
           : "no overflow"));
}

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_WRAPV (a, b, r)

Store the low-order bits of the sum of a and b into *r. Yield 1 if overflow occurred, 0 if the low-order bits are the mathematically-correct sum. See above for restrictions.

INT_SUBTRACT_WRAPV (a, b, r)

Store the low-order bits of the difference between a and b into *r. Yield 1 if overflow occurred, 0 if the low-order bits are the mathematically-correct difference. See above for restrictions.

INT_MULTIPLY_WRAPV (a, b, r)

Store the low-order bits of the product of a and b into *r. Yield 1 if overflow occurred, 0 if the low-order bits are the mathematically-correct product. See above for restrictions.

If your code includes <intprops.h> only for these _WRAPV macros, you may prefer to use Gnulib’s stdckdint module instead, as it supports similar macros that were standardized in C23 and are therefore independent of Gnulib if your code can assume C23 or later. See stdckdint.h.

Other macros are available if you do not need wrapped-around results when overflow occurs (see Checking Integer Overflow), or if you need to check for overflow in operations other than addition, subtraction, and multiplication (see Integer Type Overflow).


Next: Integer Type Overflow, Previous: Checking Integer Overflow, Up: Integer Properties   [Contents][Index]