4 ms·
AFAIK the case for undefined integer overflow is optimisations regarding loop termination, carry bit handling, and usage of 64-bit vs 32-bit registers. In light
by Asooka 10y ago
AFAIK the case for undefined integer overflow is optimisations regarding loop termination, carry bit handling, and usage of 64-bit vs 32-bit registers. In light of that can't we say that "The compiler may perform signed integer arithmetic using registers larger than the type's bits and truncate the result when writing to memory"? So e.g.
int a = INT_MAX;
int b = INT_MAX;
int c = a + b;
c > a; // true on 64 bit iff c was NOT written to memory (so -O1 and above); false on 32 bit
(c&0x7fffffff) > a; // false always
// i.e. you can always test if two positive values overflow with
((a+b)&0x7f..f)>a
Another idea I haven't seen used enough is to put values in 64-bit doubles, do your arithmetic that way and check if the final value fits in your integer type. As long as you restrict yourself to adding, subtracting and multiplying you'll get an exact result back (ok unless you run on a buggy pentium from over 25 years ago, but I think all those were recalled). A problem you have to watch out for is if you've entered the range where your ulp is larger than 1 and your math gets inexact.
- ArkyBeagle 10y agoI use float/double float values A Lot these days for arithmetic. So that reduces integer use to values read over a comms line or read otherwise from hardware. Of course, floats have their own quantum of grief.
- nayuki 10y ago> Asooka wrote: // i.e. you can always test if two positive values overflow with ((a + b) & 0x7F..F) > a This is bad advice. The act of computing (a + b) is undefined behavior. Masking it afterward will not save you against a strict compiler that exploits (or traps) all undefined behaviors.
- nkurz 10y agoI think the 'Asooka' is aware of this, and was not offering advice. Rather, he was proposing that the world would be simpler if the specs were changed so that signed addition never resulted in undefined behavior. In this simpler counterfactual world, his test would work. In our current easier to optimize world, it would not.
- Asooka 10y agoYes exactly, my point was to allow the compiler to do the addition using any registers it likes, with the only requirement being that the value is truncated when written to memory. This is less defined than "implementation defined", because a single implementation can decide to write the value to memory at an arbitrary time. But it's still better than undefined behaviour, since signed overflow is allowed to happen , just with circumstance defined behaviour. In general I would say that compilers should allow you to say "please treat undefined behaviours as platform defined". Few people write C that has to be portable between 2's complement integer processors and Minecraft logic blocks and those who do, I expect to use a fairly robust suite of static analysers and tests to guard against undefined behaviour and platform differences.