C语言移位运算 左移长度大于数据类型字节数的情况

看CMU的CSAPP课程时,遇到一个很有意思的问题,特此查询资料,记录一下

1. 测试

sizeof(int) = 4 // int 数据类型位4个字节(32位)
  • 测试程序1:a左移30位时 (正常)
#include
int main()
{
	int a = 1;
	printf("%d\n",a << 30);
	return 0;
}

输出:

4
1073741824
  • 测试程序2:a 左移31位时 (溢出)
#include
int main()
{
	int a = 1;
	printf("%d\n",a << 31);
	return 0;
}

输出:

4
-2147483648
  • 测试程序3:a左移32位时 (神奇的事情发生了)
#include
int main()
{
	int a = 1;
	printf("%d\n",a << 32);
	return 0;
}

输出:

4
1
  • 测试程序4:a左移34位时
#include
int main()
{
	int a = 1;
	printf("%d\n",a << 34);
	return 0;
}

输出:

4
4

在左移位数大于31时,编译器出现警告
[Warning] left shift count >= width of type

2. 结论

假设我们的数据类型是 由m位组成,那么在进行移位运算,移动的位数k>=m时便会出现上述问题。

C语言标准规避了在这种情况下的做法。在许多机器上,当移动一个m位的数据时,移位指令只考虑位移量的低 log2m位,故位移量即是通过计算 k mod m得到的。如上述例子,int数据类型位32位,1<<34即等价于1<<2,因为 34 mod 32 = 2

但在Java语言中,完全按照上述求模的方法进行计算!

参考:深入理解计算机系统(第三版)

你可能感兴趣的:(CSAPP)