5

Possible Duplicate:
Best way to detect integer overflow in C/C++

I am writing a function in C but the question is generic. The function takes three integers and returns some information about these three integers.

Problem I suspect here is the integers can be at their max and this can cause overflow.

For example: if I pass a as maximum value possible and b can be anything 1 - max, then in this case, will the expression (a+b)>c in if condition cause overflow? If so, how do I handle it?

My solution was to keep a long integer as temporary variable to keep value of a+b and use it in the expression but it sounds dirty way.

Refer to this snippet:

int
triangle_type(int a, int b, int c) {
    if (!((a+b)>c)&&((b+c) > a)&&((a+c>b))) {
        return -1;
    }
}
Community
  • 1
  • 1
SeattleOrBayArea
  • 2,808
  • 6
  • 26
  • 38

2 Answers2

3

On current processors, there is no real signaling overflow on integers. So on a 32 bits processors, integer arithmetic is done modulus 2^32 at the bit level. When you add up two int-s and some "overflow" happens, an overflow (or carry) bit is set in some status register (and the arithmetic operation is done modulus 2^32). If (as it is usually the case) no machine instruction tests that overflow status bit, nothing happens.

So the control flow won't change because of an overflow (it usually will change on division by zero, e.g. with a SIGEMT signal).

If you want to portably catch in C the overflow case, you could test e.g. that the sum of two positive int-s stays positive. (if it is negative an overflow did happen).

You could also be interested in bignums, e.g. use the gmp library. You could also use <stdint.h> and use carefully int32_t and int64_t with explicit casts. At last, you could (as most coders do) choose to ignore that issue.

NB: As Jonathan noticed, you may fall in the undefined behavior or the unspecified behavior case. If you really care, use bignums. However, you may choose to not care at all.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • are you saying it will evaluate the expressions correctly even though there might be an overflow? If that is the case, then my function should be fine I guess. – SeattleOrBayArea Oct 20 '12 at 06:05
  • It will evaluate your expression; I cannot promise about the correctness, because I don't know what is your expected semantics. Computation will happen modulus 2^32 (for unsigned) on 32 bits machines. I suggest you to make a tiny test to understand what is happening. – Basile Starynkevitch Oct 20 '12 at 06:08
  • ok, makes sense to do a quick test,thank you. – SeattleOrBayArea Oct 20 '12 at 06:14
  • 6
    If you overflow signed arithmetic, the behaviour is undefined. Anything might happen — and it might be that it will wraparound modulo 2^32. But, since it is formally undefined, if the compiler can spot that it will happen, it can eliminate the expression altogether. This was discussed extensively in the comp.lang.c or comp.lang.c.moderated news groups in 2011 or 2012. Don't indulge in undefined behaviour; the compiler isn't obliged to warn you that it is going to do things that are undefined. It may work on your current machine with your current compiler; it may stop working at any time. – Jonathan Leffler Oct 20 '12 at 06:26
  • "On current processors, ..." should be "In current high level languages, ...". All modern CPUs that I'm aware of do have flags that indicate signed and unsigned overflow; and yet all high level language that I've seen (including C) ignore these highly useful flags and don't even bother providing standard/portable way for programmers to test them manually. – Brendan Oct 20 '12 at 09:27
  • So it is more processor dependent than compiler dependent. The GCC compiler will probably generate a simple and fast code (at least when optimizing). – Basile Starynkevitch Oct 20 '12 at 09:59
0

You could do something like this

// returns true if a+b > c
inline int safe_sum_greater (int a, int b, int c) {
   int a1 = a / 4; int a2 = a % 4;
   int b1 = b / 4; int b2 = b % 4;
   int c1 = c / 4; int c2 = c % 4;
   int s2 = a2 + b2;

   int s1 = a1 + b1 + s2 / 4;
   s2 = s2 % 4;
   return (s1 > c1) || ( (s1 == c1) && (s2 > c2) );
}

Performance won't be bad, since only bit-wise operations will be used. I have not thought about this extensively for negative numbers, so use with care.

JohnB
  • 13,315
  • 4
  • 38
  • 65
  • I could not understand the answer, can you explain what it does. thank you – SeattleOrBayArea Oct 20 '12 at 06:53
  • You split every number into two, e.g. a = 4*a1 + a2 with |a2| < 4. Now a1, b1 are small enough to be safely added, and so are a2, b2. You have to ensure that a+b = 4*s1 + s2 with |s2| < 4 by adding that part of s2 which is too large to s1. Then you can compare s1 and c1, as well as s2 and c2. – JohnB Oct 20 '12 at 07:02