Udhay Sankar
Udhay Sankar

Reputation: 73

Detecting overflow for integer in C

#include <stdio.h>

int reverse(int);
int reverse(int x) {
  int negative = 0;
  if (x < 0)
    negative = x;
  if (negative != 0) {
    x = 0 - x;
  }
  int y = 0, temp;
  while (x > 0) {
    temp = x % 10;
    x = x / 10;
    y = (y * 10) + temp;
  }
  if (negative == 0) {
    return y;
  } else {
    return 0 - y;
  }
}
int main() {
  int x, y;
  printf("Enter your number: \n");
  scanf("%d", &x);
  y = reverse(x);
  printf("The reversed number is: %d\n", y);
  return 0;
}

This program reverses a signed integer. I was unable to check if the revered integer y, is out of bounds. I'm not able to attain clarity on the topic of overflow. If I ask the compiler using scanf to scan an integer and enter an integer that is out of range of the integer, what will happen? Does the value change as it is stored?

Upvotes: 0

Views: 370

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 149145

In standard C, overflow is an exceptional condition and behaviour is then undefined per standard. From draft n1570 for C11, 6.5 Expressions § 5:

If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.

That means that you cannot process overflow in a way that would be defined per standard. That being said, most compilers simply keep the low order bits of the result that can fit in the type representation and ignore the highest order bit(s). This is what MSVC, gcc, and clang do.

From now on, I will assume that your system uses the int32_t (resp. int16_t or int64_t) for signed int and ignores overflow. It is not mandated per standard but is common enough and is probably what your system does.

There are 2 possible overflows in your code. First is the scanf function: as said by @n.m., nothing is said for the behaviour of this family of function if the input sequence does not fit in the type. I will assume that the submitted number is acceptable as a signed int (between INT_MIN and INT_MAX). Anyway, it is trivial to have it detected by the user: just display x: if it is not the just typed number, then an overflow occured.

Second is here:

y = (y * 10) + temp;

Here again it is easy to test for overflow, by doing the reverse operations and controling that all was fine:

int next = (y * 10) + temp;
if ((next < 0) || (y != (next - temp) / 10)) {
    // an overflow occured...
    ...

In theory, nothing can guarantee that negating a positive int is a valid negative int, but this is true for the intXX_t types, so that should be enough to detect an overflow in the reverse function.

Upvotes: 0

n. m. could be an AI
n. m. could be an AI

Reputation: 120069

You seem to have two different questions regarding overflow.

  1. How to detect overflow in integer arithmetic?
  2. How to detect ovetflow in conversion functions like scanf?

The answers are as follows.

  1. There's no generic way, you have to do it on a case by case basis. For example, if y <= INT_MAX / 10, you can be sure y * 10 will not overflow. Same thing about ... + temp.
  2. scanf and friends do not have any way to protect you from overflow, other than limiting field width and thus input range (but you cannot limit the range exactly to INT_MAX if you are reading a decimal). If the scanned value doesn't fit into the destination type, the behaviour is undefined. The only way to safely convert a string with the exact range is with strtol and friends. These functions detect overflow and set errno accordingly.

Upvotes: 1

Related Questions