Reputation: 1249
I have declared 4 unsigned variables:
uint32_t empty_bucket;
uint32_t base_bucket;
uint32_t hop_size;
uint32_t ht_size;
I want to perform a signed conditional check:
if (empty_bucket < base_bucket + (hop_size - 1) - ht_size)
Knowing that base_bucket + (hop_size - 1) - ht_size
could be a negative value. What is the right casting for the operands to perform this singed operation?
NB: base_bucket + (hop_size - 1) - ht_size
could be something really close to -2^32
, so casting to signed 32-bits int32_t
could cause an overflow.
Upvotes: 2
Views: 242
Reputation: 12047
if (base_bucket + hop_size > ht_size + 1
&& empty_bucket < base_bucket + (hop_size - 1) - ht_size)
The first line checks if the right side of the comparison we want to perform is indeed a positive integer. It is done by checking that all the positive values (base_bucket
and hop_size
) are greater than all the negative values (- 1
and - ht_size
). It does this without using subtractions, so it is safe to do with unsigned integers.
@David Bowling suggested
if (empty_bucket + ht_size < base_bucket + (hop_size - 1))
the idea is basically the same, to make sure that both sides of the comparison are always positive. This works if base_bucket
and hop_size
are not both zero at the same time.
With both solutions there can theoretically still be overflow, you have to check that with your actual values. If there is overflow, use a larger type.
Please disregard my earlier mention of short-circuit evaluation, because it is not relevant. If the integer sizes are 'normal', eg. 16, 32, or 64 bits, this should work.
Upvotes: 3
Reputation: 140168
Since you're using stdint
include, you could convert the operands to 64 bit signed values, and compare that, no risk that any of the terms to the right become negative, and we have to cast the left operand to signed integer to avoid undefined/implementation behaviour when comparing signed/unsigned:
if ((int64_t)empty_bucket < ((int64_t)base_bucket + ((int64_t)hop_size - 1) - (int64_t)ht_size))
To sum it up:
Upvotes: 4