C.3.3.4 Practical Advice for Signed Overflow Issues

Ideally the safest approach is to avoid signed integer overflow
entirely. For example, instead of multiplying two signed integers, you
can convert them to unsigned integers, multiply the unsigned values,
then test whether the result is in signed range.

Rewriting code in this way will be inconvenient, though, particularly if
the signed values might be negative. Also, it may hurt
performance. Using unsigned arithmetic to check for overflow is
particularly painful to do portably and efficiently when dealing with an
integer type like uid_t whose width and signedness vary from
platform to platform.

Furthermore, many C applications pervasively assume wraparound behavior
and typically it is not easy to find and remove all these assumptions.
Hence it is often useful to maintain nonstandard code that assumes
wraparound on overflow, instead of rewriting the code. The rest of this
section attempts to give practical advice for this situation.

If your code wants to detect signed integer overflow in sum = a +
b, it is generally safe to use an expression like (sum < a) != (b
< 0).

If your code uses a signed loop index, make sure that the index cannot
overflow, along with all signed expressions derived from the index.
Here is a contrived example of problematic code with two instances of
overflow.

Because of the two overflows, a compiler might optimize away or
transform the two comparisons in a way that is incompatible with the
wraparound assumption.

If your code uses an expression like (i * 2000) / 1000 and you
actually want the multiplication to wrap around on overflow, use
unsigned arithmetic
to do it, e.g., ((int) (i * 2000u)) / 1000.

If your code assumes wraparound behavior and you want to insulate it
against any GCC optimizations that would fail to support that
behavior, you should use GCC’s -fwrapv option, which
causes signed overflow to wrap around reliably (except for division and
remainder, as discussed in the next section).

If you need to port to platforms where signed integer overflow does not
reliably wrap around (e.g., due to hardware overflow checking, or to
highly aggressive optimizations), you should consider debugging with
GCC’s -ftrapv option, which causes signed overflow to
raise an exception.