我已声明了4个无符号变量:
uint32_t empty_bucket;
uint32_t base_bucket;
uint32_t hop_size;
uint32_t ht_size;
我想执行签名条件检查:
if (empty_bucket < base_bucket + (hop_size - 1) - ht_size)
知道base_bucket + (hop_size - 1) - ht_size
可能是负值。操作员执行此操作的正确铸造是什么?
注意: base_bucket + (hop_size - 1) - ht_size
可能非常接近-2^32
,因此转换为带符号的32位int32_t
可能会导致溢出。
答案 0 :(得分:4)
由于您正在使用stdint
include,您可以将操作数转换为64位有符号值,并对此进行比较,不会有任何右边的任何条件成为负数的风险,我们必须强制转换左操作数到有符号整数,以避免在比较signed / unsigned时的未定义/实现行为:
if ((int64_t)empty_bucket < ((int64_t)base_bucket + ((int64_t)hop_size - 1) - (int64_t)ht_size))
总结一下:
答案 1 :(得分:3)
if (base_bucket + hop_size > ht_size + 1
&& empty_bucket < base_bucket + (hop_size - 1) - ht_size)
第一行检查我们想要执行的比较的右侧是否确实是正整数。通过检查所有正值(base_bucket
和hop_size
)是否大于所有负值(- 1
和- ht_size
)来完成。它不使用减法就可以做到这一点,因此使用无符号整数是安全的。
@David Bowling建议
if (empty_bucket + ht_size < base_bucket + (hop_size - 1))
这个想法基本相同,以确保比较的双方始终是积极的。如果base_bucket
和hop_size
不是同时为零,则此方法有效。
使用这两种解决方案理论上仍然可能存在溢出,您必须使用实际值进行检查。如果有溢出,请使用更大的类型。
请忽略我之前提到的短路评估,因为它不相关。如果整数大小为“正常”,例如。 16,32或64位,这应该可行。