In some C99 code, I need to check whether variable i
is in the interval [0, max]
where max
is known to be positive. The problem is that the type of the variable is allowed to be both signed and unsigned (by changing a typedef
). How does one best check that the variable is in the interval?
The straightforward approach would be:
bool is_in_interval(my_type i, my_type max) {
assert(max > 0);
return (i >= 0 && i <= max);
}
This will work fine when we have typedef int my_type;
. But when my_type
is unsigned (i.e., typedef unsigned int my_type;
), i >= 0
is always true and compilers will (rightly) warn for it, which I want to avoid. (I don't want to turn off that warning since it's useful when such comparisons actually are unintended, and just ignoring compiler warnings is not a good idea.)
My current idea is to cast i
to an unsigned type and just check the upper bound:
bool is_in_interval(my_type i, my_type max) {
assert(max > 0);
return ((size_t) i <= (size_t) max);
}
If the signed type has a two's complement representation, any negative value should be greater than max
once cast to the unsigned version, right? If so, this should work. I'm, however, uncertain whether this is an advisable approach. Is it, for example, safe to assume that signed types use two's complement on all platforms? Is there some better way to do this?
A simple solution is to do a 2-sided test.
The only attribute really lost is modest efficiency/performance. No other problems.
Although OP has certainly considered this, any solution should be weighed against this as a reference.
bool is_in_interval2(my_type i, my_type min, my_type max) {
return i >= min && i <= max;
}
// Could make this a macro or inline
bool is_in_interval(my_type i, my_type max) {
return is_in_interval2(i, 0, max);
}
I think this should shut the compiler up:
bool is_in_interval(my_type i, my_type max) {
my_type zero = 0;
assert(max > 0);
return (zero <= i && i <= max);
}
Maybe this is another straightforward approach:
bool is_in_interval(my_type i, my_type max) {
assert(max > 0);
if ((my_type)-1 > 0)
return (i <= max); // my_type is unsigned
else
return (0 <= i && i <= max); // my_type is signed
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With