Question

disclaimer: I know, unsigned integers are primitive numeric types but they don't technically overflow, I'm using the term "overflow" for all the primitive numeric types in general here.

in C or C++, according to the standard or to a particular implementation, there are primitive numeric types where given an arithmetic operation, even if this operation could possibly overflow, I can save the result + plus the part that overflows ?

Even if this sounds strange, my idea is that the registers on modern CPUs are usually much larger than a 32 bit float or a 64 bit uint64_t, so there is the potential to actually control the overflow and store it somewhere.

Was it helpful?

Solution

No, the registers are not "usually much larger than a 64 bit uint64_t".

There's an overflow flag, and for a limited number of operations (addition and subtraction), pairing this single additional bit with the result is enough to capture the entire range of outcomes.

But in general, you'd need to cast to a larger type (potentially implemented in software) to handle results that overflow the type of your input.

Any operations that do this sort of thing (for example some 32-bit processors had a 32x32 => 32 high, 32 low wide multiply instruction) will be provided by your compiler as intrinsic functions, or via inline assembly.

look, I found a 64-bit version of that, named Multiply128 and the matching __mul128 instrinsic available in Visual C++

OTHER TIPS

See @Ben Voigt about larger registers.

There really may only be an overflow bit that could help you.

Another approach, without resorting to wider integers, is to test overflow yourself:

unsigned a,b,sum;
sum = a + b;
if (sum < a) {
  OverflowDetected();  // mathematical result is `sum` + UINT_MAX + 1
}

Similar approach for int.
The following likely may be simplified - just don't have it at hand.

[Edit] My below apporach has potentila UB. For a better way to detect int overflow, see Simpler method to detect int overflow

int a,b,sum;
sum = a + b;
// out-of-range only possible when the signs are the same.
if ((a < 0) == (b < 0)) {
  if (a < 0) {
    if (sum > b) UnderflowDetected();
  }
  else {
    if (sum < b) OverflowDetected();
  }

For floating point type, you can actually 'control' the overflow on x86 platform. With these functions "_control87, _controlfp, __control87_2", you can Gets and sets the floating-point control word. By default, the run-time libraries mask all floating-point exceptions; you can unmask them in your code, so when a overflow occurs, you'll get an exception. However, the code we write today, all assume that the floating point exceptions are masked, so if you unmask them, you'll encounter some problem.

You can use these functions to get the status word.

For floating point types the results are well defined by the hardware, and you're not going to be able to get much control without working around C/C++.

For integer types smaller than int, they will be upsized to an int by any arithmetic operation. You will probably be able to detect overflow before you coerce the result back into the smaller type.

For addition and subtraction you can detect overflow by comparing the result to the inputs. Adding two positive integers will always yield a result larger than either of the inputs, unless there was overflow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top