本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第2章,建议14-3,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
建议14-3:移位的数量必须大于等于0且小于操作数的位数
如果被移位的操作数的长度为n,那么移位的数量必须大于等于0且小于n。因此,在一次单独的操作中不可能将所有的位从变量中移出。例如,一个int型的整数是32位,并且n是一个int型整数,那么n << 31和n << 0是合法的,但n << 32和n << -1是不合法的。因此,我们在进行移位运算的时候必须做相关测试。示例代码如下所示:
unsigned int x;
unsigned int y;
unsigned int result;
/*初始x,y,result*/
if(y>=sizeof(unsigned int) * CHAR_BIT)
{
// 错误处理
}
else
{
result=x>>y;
}
这里还需要说明的是,对于变量x与y,C99规定:
对于x<2y可以用结果类型表示,那么这个表达式就是结果值,否则,其行为是未定义的;如果x是无符号类型,则x<2y,是根据“结果类型可以表达的最大值加1”进行求模运算得到的结果。需要注意的是,尽管在C99中指定了无符号整数的取模行为,无符号整数溢出还是常常导致出乎意料的值以及因此产生的潜在安全风险。
对于x>>y,如果x是无符号类型或非负值的有符号类型,那么x>>y的移位结果为 x/2y的商的整数部分;如果x是有符号类型的负值,那么x>>y的移位结果是由编译器所定义的。因此,对一个带符号整数进行右移运算和将它除以2的某次幂不一定是等价的。要证明这一点很容易,考虑(-1) >> 1的值,它的执行结果不可能为0,而在大多数C语言编译器中(-1)/2的结果都是0。