John Regehr的博客文章A Guide to Undefined Behavior in C and C++, Part 1包含以下“安全”功能,用于“执行整数除法而不执行未定义的行为”:
int32_t safe_div_int32_t (int32_t a, int32_t b) {
if ((b == 0) || ((a == INT32_MIN) && (b == -1))) {
report_integer_math_error();
return 0;
} else {
return a / b;
}
}
当a = INT32_MIN且b = -1时,我想知道除法(a / b)有什么问题。这是不确定的?如果是这样的话?
答案 0 :(得分:15)
我认为这是因为INT32_MIN的绝对值比INT32_MAX大1。所以INT32_MIN / -1实际上等于INT32_MAX + 1会溢出。
因此对于32位整数,有4,294,967,296个值
负数有2,147,483,648个值(-2,147,483,648到-1)
零(0)有1个值
正数的数值为2,147,483,647(1到2,147,483,647),因为0与正数相差1个值。
答案 1 :(得分:3)
这是因为int32_t
使用二进制补码表示,而二进制补码中N
位的数字从−2^(N−1)
到2^(N−1)−1
。因此,当您执行除法时,您会得到:-2^(31) / -1 = 2^(N-1)
。请注意,结果大于2^(N-1)-1
,这意味着您会溢出!
答案 2 :(得分:2)
其他海报对于溢出的原因是正确的。大多数机器上溢出的含义是INT_MIN / -1 => INT_ MIN。乘以-1时会发生同样的事情。这是意想不到的,可能是危险的结果。我看到定点电机控制器失控,因为它没有检查这种情况。
答案 3 :(得分:1)
因为INT32_MIN定义为(-INT32_MAX-1)= - (INT32_MAX + 1),当除以-1时,这将是(INT32 + MAX)=>有一个整数溢出。我必须说,这是检查溢出的好方法。刻意写的代码。 +1给开发者。