Рассмотрим функцию (одну из возможных ее реализаций), которая будет нулевать справа N бит беззнакового короткого значения (или любого другого неподписанного интегрального типа). Возможная реализация может выглядеть следующим образом:Бит-сдвиг влево и отбрасывание битов
template<unsigned int shift>
unsigned short zero_right(unsigned short arg) {
using type = unsigned short;
constexpr type mask = ~(type(0));
constexpr type right_zeros = mask << shift; // <-- error here
return arg & right_zeros;
}
int check() {
return zero_right<4>(16);
}
С помощью этого кода, все компиляторы я имею доступ жаловаться, так или иначе, о возможном переполнении. Clang является наиболее явными один, со следующими ясным сообщением:
error: implicit conversion from 'int' to 'const type' (aka 'const unsigned short') changes value from 1048560 to 65520 [-Werror,-Wconstant-conversion]
Этого код выглядит хорошо определен и ясно как день для меня, но когда 3 Составителей жалуются, я становлюсь очень нервным. Я что-то упустил? Есть ли шанс, что происходит что-то подозрительное?
P.S. В то время как альтернативные реализации zeriong из оставшихся X-бит могут быть приветствуемыми и интересными, основное внимание в этом вопросе имеет обоснованность кода, опубликованного.
@TavianBarnes, они не могут быть повышен до подписанных Интсов для беззнаковых аргументов. – SergeyA
Не то, о чем вы просите, но что-то, о чем вы можете знать (и не защищаете), состоит в том, что если вы оставили сдвиг беззнакового целого на «n» биты, где «n» есть> = количество бит в тип, который вы меняете, то это неопределенное поведение. –
@SergeyA Но это все еще проблема: thew результат '<<' is int, а не короткий. Преобразование результата 'mask << shift' обратно в' type' перед присваиванием делает ошибку уходить. –