29

There's (1):

// assume x,y are non-negative
if(x > max - y) error;

And (2):

// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;

Whichs is preferred or is there a better way.

4
  • 1
    Actually the duplicate is not a duplicate at all, it is talking about unsigned that have well-defined wraparound semantics, whereas overflowing a signed integer is undefined behaviour in C. Commented Mar 16, 2015 at 15:33
  • 2
    There is no need to check both sum < x and sum < y. Commented Oct 7, 2015 at 13:43
  • This was previously closed as a duplicate of How to detect integer overflow?, but that's about unsigned where wrapping is well-defined behaviour. signed int is harder because you can't just add and then check if it overflowed, that would already be UB and thus compilers can assume there was no overflow! Commented Feb 4, 2019 at 6:00
  • Possible duplicate of How do I detect unsigned integer multiply overflow? Commented May 7, 2019 at 15:42

3 Answers 3

65

Integer overflow is the canonical example of "undefined behaviour" in C (noting that operations on unsigned integers never overflow, they are defined to wrap-around instead). This means that once you've executed x + y, if it overflowed, you're already hosed. It's too late to do any checking - your program could have crashed already. Think of it like checking for division by zero - if you wait until after the division has been executed to check, it's already too late.

So this implies that method (1) is the only correct way to do it. For max, you can use INT_MAX from <limits.h>.

If x and/or y can be negative, then things are harder - you need to do the test in such a way that the test itself can't cause overflow.

if ((y > 0 && x > INT_MAX - y) ||
    (y < 0 && x < INT_MIN - y))
{
    /* Oh no, overflow */
}
else
{
    sum = x + y;
}
Sign up to request clarification or add additional context in comments.

8 Comments

Btw, can you comment on the performance of this solution compared to other alternative solutions?
It makes little sense to compare the performance against an incorrect solution. What other correct solution did you have in mind?
the other usual way seem to be casting to a wider type. I'm not sure of a third alternative but there are surely more.
@Pacerier Casting to a wider type is not possible if you're already working with the largest type on the platform.
@Tuntable: What every single compiler does is optimizations which can lead to horror: blog.llvm.org/2011/05/…
|
2

You can really only check for overflow with unsigned integers and arithmatic:

unsigned a,b,c;
a = b + c;
if (a < b) {
    /* overflow */
}

The behavior of overflow with signed integers is undefined in C, but on most machines you can use

int a,b,c;
a = b + c;
if (c < 0 ? a > b : a < b) {
    /* overflow */
}

This may require compile-time flags to get the compiler to enforce wrapping semantics, and won't work on machines that use any kind of saturating or trapping arithmetic

3 Comments

Checking for overflow after the fact with signed integers isn't correct. It's undefined behaviour, so compilers will happily optimize out the checks without passing a switch like -fwrapv to enable signed wrapping as a language extension. It's not just a portability issue across architectures.
Overflow for signed integers can also be checked. See securecoding.cert.org/confluence/display/c/…
Nope, modern gcc breaks your signed int example. Signed integer not overflowing on ARM64?.
-7

You only have to check one of them. If x + y overflows, it will be less than both x and y. Hence:

int sum = x + y;
if (sum < x) error;

should be sufficient.

The following site has a bunch of stuff about integer overflow:

http://www.fefe.de/intof.html

If you want to handle negative numbers, it can be expanded:

int sum = x + y;
if (y >= 0) {
   if (sum < x) error;
} else {
   if (sum > x) error;
}

4 Comments

The original poster specified non-negative integers, but I've added code to handle negative numbers.
This isn't correct - once x + y has overflowed, the program has undefined behaviour. You have to check before you actually execute the overflowing operation - just as you do for integer division by zero.
If anything is more wrong than this answer, then possibly the page it links to.
This is correct for unsigned though, and I think it's really good for that case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.