Integer overflow checking with C23

While I wasn’t looking, C23 has standardized checked integer arithmetic functions, replacing the old “__builtin_mul_overflow()” compiler intrinsics that shipped with GCC and Clang.

#include <stdckdint.h>
bool ckd_add(type1 *result, type2 a, type3 b);
bool ckd_sub(type1 *result, type2 a, type3 b);
bool ckd_mul(type1 *result, type2 a, type3 b);

The operations are performed equivalently to doing them in the mathematically reasonable way (as normal integers in ℤ, not modulo-something), and then truncating them to fit into the *result integer. The function returns true if the resulting value could not be represented in *result’s integer type.

To check for overflow of two integers a and b, define a variable for the calculation result and do:

int result;
if (ckd_mul(&result, a, b)) {
  errx(1, "a * b overflow or wraparound");
}

These semantics remove having to worry of the unintuitive difference between (undefined) integer overflow and (well-defined) unsigned integer wraparound. (The “arithmetic” ways for checking overflow/wraparound differ substantially for signed and unsigned integers, otherwise.)

The feature is available in: GCC 14+, Clang 18+, both released in Q2 2024.

Further references

The Integer section of the SEI C Coding Standard wiki has some excellent guidance for correct overflow and wraparound checks, also for older compilers. Specifically, these sections are:

David Svoboda, who is involved here, is the same person who proposed the extension to the C23 standard.

Jens Gustedt’s Blog has a longer post on the topic as well with more practical examples and a discussion of how to emulate the new interface based on the older macros that GCC and LLVM offered before C23.

The __builtin_mul_overflow() macro and friends were introduced in GCC 5 (2015) and Clang 3.4 (2014).

Comments