我有两个有符号的整数,我想减去它们。我需要知道它是否溢出。
int one;
int two;
int result = two-one;
if (OVERFLOW) {
printf("overflow");
} else {
printf("no overflow");
}
这样的事情。有没有办法做到这一点?
答案 0 :(得分:10)
你需要在之前发现溢出(或下溢)。一旦发生这种情况,你就会进入未定义的行为土地并且所有的赌注都已关闭。
#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;
}
答案 1 :(得分:6)
首先,签名计算中的溢出会导致C中的未定义行为。
其次,忘记UB一秒钟,并坚持2补码机器的典型溢出行为:溢出是由于结果从第一个操作数“错误的方向”“移动”,即结果最终大于第一个操作数,第二个操作数为正(或小于第二个操作数为第一个操作数)。
在你的情况下
int one, two;
int result = two - one;
if ((result < two) != (one > 0))
printf("overflow");
答案 2 :(得分:1)
您可以以更高的精度进行比较。假设你有32位整数。您可以将它们提升为64位整数,减去,然后将该结果与自身转换为32位然后再将其再次转换为64位。
我不会这样做int
,因为该语言无法保证大小... int32_t
和来自int64_t
的{{1}} (来自C99)。
如果您使用的是Windows,则可以使用<inttypes.h>
等,这会在溢出时返回错误代码。