我已经声明了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
可能是负值。操作数以执行此唱歌的操作的正确铸件是什么?
nb: base_bucket + (hop_size - 1) - ht_size
可能是真正接近 -2^32
的东西,因此施放到签名的32位int32_t
可能会导致溢出。
由于您使用的是stdint
,因此您可以将操作数转换为64位签名的值,并比较,没有风险,即正确的任何条款都会变成负面,我们有要施放左操作数以签名整数,以避免比较签名/无符号时避免未定义/实现行为:
if ((int64_t)empty_bucket < ((int64_t)base_bucket + ((int64_t)hop_size - 1) - (int64_t)ht_size))
总结:
- 没有溢出的风险(我可能在右侧投射得太多)
- 签名实体之间的比较
- 缺点,64位转换可能会对32位体系结构的性能产生负面影响
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保龄球建议
if (empty_bucket + ht_size < base_bucket + (hop_size - 1))
这个想法基本上是相同的,以确保比较的双方始终是积极的。如果base_bucket
和hop_size
同时不是零。
使用两种解决方案,理论上仍然可以溢出,您必须使用实际值检查一下。如果有溢出,请使用较大的类型。
请忽略我以前提到的短路评估,因为这是无关紧要的。如果整数大小为"正常",例如。16、32或64位,这应该有效。