5 ms·
Am I the only one who thinks that writing if (x + y < x) is utterly insane? It completely breaks the abstraction of algebra that's being used in the lang
by efaref 10y ago
Am I the only one who thinks that writing
if (x + y < x)
is utterly insane? It completely breaks the abstraction of algebra that's being used in the language. Much better would be:
if (ADDITION_WOULD_OVERFLOW_INT(x, y))
{
...
}
This is (a) far easier to read, and (b) more likely to be more correctly implemented as something like:
#define ADDITION_WOULD_OVERFLOW_INT(a, b) \
(((a) > 0 && (b) > 0 && (b) > INT_MAX - (a)) || \
((a) < 0 && (b) < 0 && (b) < INT_MIN - (a)))
For bonus points you could write this as part of the compiler support library to derive the types and limits automatically, or even define it as part of the compiler. Why do GCC/clang not have:
__builtin_addition_would_overflow(a, b)
?
- Kristine1975 10y ago>Why do GCC/clang not have: __builtin_addition_would_overflow(a, b) But they do: https://news.ycombinator.com/item?id=11711608 https://news.ycombinator.com/item?id=11711608 :-)
- efaref 10y agoThe API for those is equally insane (they replace the arithmetic operation). See my sibling comment for a more reasonable proposal.
- kevinnk 10y ago> Why do GCC/clang not have: __builtin_addition_would_overflow(a, b) Both GCC and Clang have __builtin_add_overflow, which as far as I can tell do exactly what you're proposing.
- efaref 10y agoA comment below reminded me of these: https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins..., which are close, but have an insane API as they replace your arithmetic operations with ugliness. I think they can be fixed with sensible macros, though: #define ADDITION_WOULD_OVERFLOW(a, b) \ ({ typeof((a) + (b)) __r; __builtin_add_overflow((a), (b), &__r); }) Hopefully the compiler would optimise: if (ADDITION_WOULD_OVERFLOW(a, b)) { return 0; } return a + b; to only do the addition once.
- efaref 10y agoI just tried this, and GCC6 does indeed optimise this correctly: 0000000000400560 <maybe_overflow>: 400560: 01 f7 add %esi,%edi 400562: 70 03 jo 400567 <maybe_overflow+0x7> 400564: 89 f8 mov %edi,%eax 400566: c3 retq 400567: 31 c0 xor %eax,%eax 400569: c3 retq
- Kristine1975 10y agoHow about: #define ADD_OR_DEFAULT(a, b, d) \ ({ typeof((a) + (b)) r; __builtin_add_overflow((a), (b), &r) ? (d) : r; }) and then: return ADD_OR_DEFAULT(a, b, 0); P.S: Names beginning with two underscores are reserved for the implementation.
- efaref 10y agoThe problem with solutions like this is that they break the abstraction of using algebraic notation for calculations. We're conditioned to expect calculations to be written in algebraic notation, and indeed one of the original selling points of C is that it lets you express calculations in that form. To undo that is a massive shame. The calculation itself absolutely MUST look like this: a + b While maybe it's not too bad for simple addition, think of compound expressions with multiple terms.
- esrauch 10y agoYou didn't consider y < 0
- efaref 10y agoI did. Look at the second line of the macro expansion.