I have been thinking about integer (type int) overflows, and it occurs to me that division could overflow.
Example: On my current platform, I have
INT_MIN == -INT_MAX - 1
and thus
INT_MIN < -INT_MAX
and thus
INT_MIN / -1 > -INT_MAX / -1
and thus
INT_MIN / -1 > INT_MAX.
Hence, the division ( INT_MIN / -1 ) does overflow.
So, I have two questions:
What (cross-platform) C code could one write in order to prevent division overflows (for type (signed) int)?
What guarantees (in C or C++ standard) might help to devise the code?
For example, if the standard guarantees that we have either
INT_MIN == -INT_MAX - 1
or
INT_MIN == -INT_MAX,
then the following code appears to prevent overflows.
#include <limits.h>
/*
Try to divide integer op1 by op2.
Return
0 (success) or
1 (possibly overflow prevented).
In case of success, write the quotient to res.
*/
int safe_int_div(int * res, int op1, int op2) {
/* assert(res != NULL); */
/* assert(op2 != 0); */
if ( op1 == INT_MIN && op2 == -1 ) {
return 1;
}
*res = op1 / op2;
return 0;
}
What guarantees (in C or C++ standard) might help to devise the code?
C specifies signed integer representation as using 1 of 3 forms: sign and magnitude, two’s complement, or ones’ complement. Given these forms, only division by 0 and two’s complement division of INT_MIN/-1
may overflow.
Update: 2023: C23 is expected only support two’s complement.
What (cross-platform) C code could one write in order to prevent division overflows (for type (signed) int)?
int safe_int_div(int * res, int op1, int op2) {
if (op2 == 0) {
return 1;
}
// 2's complement detection
#if (INT_MIN != -INT_MAX)
if (op1 == INT_MIN && op2 == -1) {
return 1;
}
#endif
*res = op1 / op2;
return 0;
}