I want to have a generic method that can detect overflows in all types such as char, unsigned char, short, unsigned short, int32, unsigned int32, long, unsigned long, int64, unsigned int64 etc
On later C we can use __builtin_add_overflow_p
to detect the overflow on addition. The macro can be like this
#define ADD_OVERFLOW(a, b) __builtin_add_overflow_p (a, b, (__typeof__ ((a) (b))) 0)
The issue is this will not detect overflow in 8bit or 16bit types such as char or short. Need a generic and efficient mechanism to detect the overflow. Efficient means fewer cpu cycles as possible because the check need to be put in many places. Inefficient check can slow down the program. Therefore Efficiency is a must
I tried this also
#define ADD_OVERFLOW(a, b) ((__typeof__(a))(a b) < a)
It did not work for some signed types eg, int32 Is there a generic solution that works for all types in C ?
CodePudding user response:
__builtin_add_overflow_p
does work with 8 and 16 bit types. The problem is that (__typeof__ ((a) (b)))
is int
, and it doesn't overflow in int
.
What you probably want is for a
and b
to be the same type and to check if the addition overflows in that type:
template<typename T>
constexpr bool add_overflow(T a, T b) {
return __builtin_add_overflow_p(a, b, T{0});
}
static_assert(add_overflow((signed char) 125, (signed char) 100));
static_assert(!add_overflow((signed char) 125, (signed char) -3));
// Or if you *must* use a macro:
#define ADD_OVERFLOW(a, b) __builtin_add_overflow_p(a, b, \
std::enable_if_t< \
std::is_same_v<std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>, \
std::decay_t<decltype(a)>>{0})