Hacker News new | ask | show | jobs
by Retr0id 25 days ago
GCC -O1 and clang -O1 will both optimize this function under the assumption that inputs that cause signed integer overflow are never passed:

    int will_overflow(int a, int b) {
        int sum = a + b;
        if (b > 0 && sum < a)
            return 1;
        return 0;
    }
2 comments

Right, good example, and both GCC and Clang offer well understood parameters for deciding, per compilation unit, what behavior you want for signed overflow (-fwrapv, -fno-strict-overflow, etc), so in reality it's quite far from spooky arbitrary nasal demons.
Wouldn’t be better to check both inputs before against the max value of that type instead of actually doing the overflow?
There are lots of better ways of doing this, but knowing why this one is bad/wrong requires the mental model described upthread.

(But also, what you describe would be incorrect, since two <MAX values can add to a value that is >MAX, and overflow)

> But also, what you describe would be incorrect, since two <MAX values can add to a value that is >MAX, and overflow

I was maybe unclear. I meant, if you know a sum can introduce overflow (because you have a check right after), why not check the inputs before doing the sum, instead of checking the sum?

You can do something like

       (y > 0 && x > INT_MAX - y) 
    || (y < 0 && x < INT_MIN - y)
and hope the optimizer turns it back into just checking the result. Or you use -fwrapv to concretize the ISO ambiguity and specify the natural two's complement semantics, checking overflow with the classic Hacker's Delight formula;

    ((x ^ s) & (y ^ s)) < 0

But the best way is to use the intrinsic __builtin_add_overflow or, depending on compiler support, its C23 standardization via <stdckdint.h> and ckd_add etc.