I'm trying to make use of errno
to detect if I've performed an operation that causes overflow. However, although I've written a function which deliberately overflows, errno == ERANGE
is false. What's going on here?
Here's the code:
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[]) {
unsigned char c = 0;
int i;
for (i = 0; i< 300; i++) {
errno = 0;
c = c + 1;
if (errno == ERANGE) {// we have a range error
printf("Overflow. c = %u\n", c);
} else {
printf("No error. c = %u\n", c);
}
}
return 0;
}
I expected this to give an overflow error at the point where we added one to 255, but there is no error. Here's the (truncated) output:
No error. c = 245
No error. c = 246
No error. c = 247
No error. c = 248
No error. c = 249
No error. c = 250
No error. c = 251
No error. c = 252
No error. c = 253
No error. c = 254
No error. c = 255
No error. c = 0
No error. c = 1
No error. c = 2
No error. c = 3
No error. c = 4
No error. c = 5
No error. c = 6
No error. c = 7
No error. c = 8
No error. c = 9
Can someone explain why it doesn't detect the error, and how I might change it or otherwise make a function that can detect if my value has overflowed? Note: ultimately I want to be doing this with long int
s, so it's not possible to simply convert it to a larger data type.
EDIT:
I've since found some simple functions to detect overflow from addition and multiplication of integral data types, respectively. It doesn't cover all situations, but it covers a lot of them.
Multiplication:
int multOK(long x, long y)
/* Returns 1 if x and y can multiply without overflow, 0 otherwise */
{
long p = x*y;
return !x || p/x == y;
}
Signed addition:
int addOK(long x, long y)
/* Returns 1 if x and y can add without overflow, 0 otherwise */
{
long sum = x+y;
int neg_over = (x < 0) && (y < 0) && (sum >= 0);
int pos_over = (x >= 0) && (y >= 0) && (sum < 0);
return !neg_over && !pos_over;
}
Unsigned addition:
int unsignedAddOK(unsigned long x, unsigned long y)
/* Returns 1 if x and y can add without overflow, 0 otherwise */
{
unsigned long sum = x+y;
return sum > x && sum > y;
}