Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check whether variable of unknown signedness is in interval

Tags:

c

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?

like image 286
Fredrik Savje Avatar asked Feb 14 '16 04:02

Fredrik Savje


3 Answers

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);
}
like image 112
chux - Reinstate Monica Avatar answered Oct 19 '22 05:10

chux - Reinstate Monica


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);
}
like image 3
sh1 Avatar answered Oct 19 '22 05:10

sh1


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
}
like image 2
nalzok Avatar answered Oct 19 '22 05:10

nalzok