C-如何在未签名操作数之间进行签名比较



我已经声明了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_buckethop_size)大于所有负值(- 1- ht_size)来完成。它在不使用减法的情况下执行此操作,因此可以安全地使用未签名的整数。

@david保龄球建议

if (empty_bucket + ht_size < base_bucket + (hop_size - 1)) 

这个想法基本上是相同的,以确保比较的双方始终是积极的。如果base_buckethop_size同时不是零。

使用两种解决方案,理论上仍然可以溢出,您必须使用实际值检查一下。如果有溢出,请使用较大的类型。

请忽略我以前提到的短路评估,因为这是无关紧要的。如果整数大小为"正常",例如。16、32或64位,这应该有效。

相关内容

  • 没有找到相关文章

最新更新