如何重写此测试以使测试本身不会溢出?我可以使用(size_t) -1
是奇数(2减去1的幂)的事实吗?
size_t size;
...
if ((size * 3U + 1U) / 2U > (size_t) -1) {
/* out of address space */
}
编辑:抱歉,我的问题标题错了。我不想检查(n * 3 + 1) / 2
是否会溢出,但是n / 2 * 3 + n % 2 * 2
是否会溢出。我改变了标题。感谢您对错误问题的正确回复。
答案 0 :(得分:2)
以下是这个精确公式的解决方案,其背后的推理不适用于一般情况,但对于给定的一个,以及许多其他情况,它确实如此。
当size*3 + 1
无法表示时,溢出恰好发生,无符号整数除法永远不会溢出。所以,你的情况应该是size*3 + 1 > max_value
。这里,max_value是设置了所有位的无符号值,使用(size_t)-1
生成。
+1
可以简单地移动到右侧而不调用溢出,因为max_value肯定大于1,所以我们到达size*3 > max_value - 1
。同样,可以在不调用溢出的情况下移动*3
。所以你需要检查的是size > (max_value - 1)/3
。
请注意,与我原先所说的相反(mea culpa),size > max_value/3
不起作用,因为当整数类型为无符号时,max_value 是3的倍数(条件是有一个偶数位可用于正数)。因此,当大小为0x5555
时,我们会得到3*size = 0xffff
和3*size + 1 = 0x0000
。很抱歉混淆了。