[ACCEPTED]-How to detect overflow when subtracting two signed 32 bit numbers in C?-integer-overflow

Accepted answer
Score: 14

You need to catch the overlow (or underflow) before it 2 happens. Once it happens you're in Undefined Behaviour land 1 and all bets are off.

#include <limits.h>
#include <stdio.h>

int sum_invokes_UB(int a, int b) {
  int ub = 0;
  if ((b < 0) && (a < INT_MIN - b)) ub = 1;
  if ((b > 0) && (a > INT_MAX - b)) ub = 1;
  return ub;
}

int main(void) {
  printf("(INT_MAX-10) + 8: %d\n", sum_invokes_UB(INT_MAX - 10, 8));
  printf("(INT_MAX-10) + 100: %d\n", sum_invokes_UB(INT_MAX - 10, 100));
  printf("(INT_MAX-10) + INT_MIN: %d\n", sum_invokes_UB(INT_MAX - 10, INT_MIN));
  printf("100 + INT_MIN: %d\n", sum_invokes_UB(100, INT_MIN));
  printf("-100 + INT_MIN: %d\n", sum_invokes_UB(-100, INT_MIN));
  printf("INT_MIN - 100: %d\n", sum_invokes_UB(INT_MIN, -100));
  return 0;
}
Score: 8

Firstly, overflow in signed calculations 10 causes undefined behavior in C.

Secondly, forgetting 9 about UB for a second and sticking to the 8 typical overflow behavior of a 2's complement 7 machine: overflow is revealed by the fact 6 that result "moves" in the "wrong direction" from 5 the first operand, i.e when the result ends 4 up greater than the first operand with positive 3 second operand (or smaller than the first 2 operand with negative second operand).

In 1 your case

int one, two;

int result = two - one;
if ((result < two) != (one > 0))
  printf("overflow");
Score: 0

You can do it with higher precision and 9 compare. Say you have 32-bit integers. You 8 can promote them to 64-bit integers, subtract, then 7 compare that result with itself cast to 6 32-bit and then up again to 64 bits.

I wouldn't 5 do it this way with int, because the language 4 doesn't give you guarantees on sizes... Maybe 3 int32_t and int64_t from <inttypes.h> (from C99).

If you're on Windows 2 use can use ULongSub() etc, which returns an error 1 code on overflow.

Score: 0

There are 2 cases to consider on evaluating 2 a-b:

  1. a-b may underflow, iff b>0 && a<0 and a-b < min == a<min+b
  2. a-b may overflow, iff b<0 && a>0 and a-b > max == -b>max-a

This leads us on simplifying the a case 1 to

#include <limits.h>

int sub_invokes_UB(int a, int b) {
  if ((b > 0) && (a < INT_MIN + b)) ub = 1; // error
  if ((b < 0) && (a > INT_MAX + b)) ub = 1; // error
  return 0; // ok
}

More Related questions