让我们考虑一个函数(可能的实现之一),它将无符号短整型值(或任何其他无符号整型)的右侧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是最明确的一个,它有以下清晰的消息:
错误:从'int'隐式转换为'const type'(也称为'const unsigned short')会将值从1048560更改为65520 [-Werror,-Wconstant-conversion]
对我来说,这个代码看起来定义良好,清晰易懂,但当3个编译器抱怨时,我变得非常紧张。 我是否错过了什么? 真的有可能发生一些可疑的事情吗?
附注:虽然对左侧X位进行零化的替代实现可能是受欢迎和有趣的,但这个问题的主要重点是发布的代码的有效性。
<<
的结果是 int,而不是 short。在赋值之前将mask << shift
的结果转换回type
可以消除错误。 - Mr Lister