如何在无符号操作数之间进行带符号比较?
How to perform signed comparison between unsigned operands?
我声明了 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
可能会导致溢出.
由于您使用的是 stdint
include,您可以将操作数转换为 64 位有符号值,然后进行比较,不会有任何右侧项变为负数的风险,我们必须强制转换左操作数为有符号整数,以避免在比较 signed/unsigned:
时出现 undefined/implementation 行为
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 Bowling 建议
if (empty_bucket + ht_size < base_bucket + (hop_size - 1))
思路基本一致,确保比较的两边总是正的。如果 base_bucket
和 hop_size
不同时都为零,则此方法有效。
对于这两种解决方案,理论上仍然会溢出,您必须使用实际值进行检查。如果溢出,请使用更大的类型。
请忽略我之前提到的短路评估,因为它不相关。如果整数大小为 'normal',例如。 16、32 或 64 位,这应该可以。
我声明了 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
可能会导致溢出.
由于您使用的是 stdint
include,您可以将操作数转换为 64 位有符号值,然后进行比较,不会有任何右侧项变为负数的风险,我们必须强制转换左操作数为有符号整数,以避免在比较 signed/unsigned:
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 Bowling 建议
if (empty_bucket + ht_size < base_bucket + (hop_size - 1))
思路基本一致,确保比较的两边总是正的。如果 base_bucket
和 hop_size
不同时都为零,则此方法有效。
对于这两种解决方案,理论上仍然会溢出,您必须使用实际值进行检查。如果溢出,请使用更大的类型。
请忽略我之前提到的短路评估,因为它不相关。如果整数大小为 'normal',例如。 16、32 或 64 位,这应该可以。