В некотором коде C99 мне нужно проверить, не является ли переменная i
в интервале [0, max]
, где max
, как известно, является положительным. Проблема в том, что тип переменной разрешен как подписанный, так и неподписанный (путем изменения typedef
). Как лучше проверить, что переменная находится в интервале?Проверьте, находится ли переменная неизвестной подписи в интервале
Прямое подход будет:
bool is_in_interval(my_type i, my_type max) {
assert(max > 0);
return (i >= 0 && i <= max);
}
Это будет работать хорошо, когда у нас есть typedef int my_type;
. Но когда my_type
является неподписанным (то есть, typedef unsigned int my_type;
), i >= 0
всегда истинно, и компиляторы (по праву) предупреждают об этом, чего я хочу избежать. (Я не хочу отключать это предупреждение, так как это полезно, когда такие сравнения действительно непреднамеренны, и просто игнорирование предупреждений компилятора - это не очень хорошая идея.)
Моя нынешняя идея состоит в том, чтобы сделать i
неподписанным типом и просто проверить верхнюю границу:
bool is_in_interval(my_type i, my_type max) {
assert(max > 0);
return ((size_t) i <= (size_t) max);
}
Если подписанный тип имеет комплемента представление в две, любое отрицательное значение должно быть больше, чем когда-то max
гипсе без знака версии, не так ли? Если это так, это должно сработать. Однако я не уверен, что это целесообразный подход. Можно ли, например, с уверенностью предположить, что подписанные типы используют два дополнения на всех платформах? Есть ли лучший способ сделать это?
Это не сработает, если ваше подписанное тестовое значение, интерпретируемое как 'unsigned', может быть больше (без знака)' MAX/2'. Так ли это? (Возможно, я имею в виду * меньше *.) – usr2564301
Я уверен, что гарантировано, что отрицательное значение, переданное совместимому неподписанному типу, будет больше, чем любое положительное значение для исходного типа. Однако, если вы это сделаете, вы будете застонать о «странном коде». – sh1
@Jongware Извините, я не совсем понимаю, что вы имеете в виду. 'MAX' не является пределом типа (например,' INT_MAX' или 'UINT_MAX'). Использование заглавных букв вводило в заблуждение (теперь это изменилось). –