您的位置:首页 > 编程语言 > C语言/C++

C语言中移位操作符那点事

2013-10-10 17:35 281 查看
最近碰到几个有意思的移位操作符的题目,下面先来看看这几个题目(32bit-CPU架构):

1.
int i = 1;

printf("%d\n",i<<32);

2.
printf("%d\n",1<<32);

3.
int i=-1;

printf("%d,%d\n",i<<32, i<<31, i>>32, i>>31);

这几个题目看起来都很简单,但很容易中招哦,不信自己先给个答案,再来验证下吧!

第一题:

和编译器的处理有关,正整数1在计算机中按照补码存储形式为0x 00 00 00 01,编译器默认将移位操作符的右边数对32取余,因此左移32位等同于左移0位,答案仍为1,对于右移也适用。

第二题:

这个常数的移动操作编译器的处理略有不同,如果按照第一题来解,答案应该为1,可是编译后执行发现结果却为0,说明这里的1<<32编译器并没有对32取余,左移补0,因此,左移32位后则为0,这里再通过 printf("%d\n",1<<33); 验证,发现结果仍为0,说明33并没有对32取余(如果取余的话结果应该为1<<1=2)。

第三题:

有符号负整数-1,在内存中补码形式存储为0xFFFFFFFF,因为有符号位1的存在,变量的右移都补1,而左移仍补0,变量的左右移右操作数会对32取余,则左移32位和右移32位均等同于不移动,结果仍为-1,而左移31位补零,补码0xFFFFFFFF左移31位为0x80000000,可以自己手动还原为原码检验,打印到屏幕上为-2147483648,而右移31位,补码0xFFFFFFFF右移补1,因此右移任何位都不变,仍为-1。

总结:1. 编译器对常数的左右移位操作与变量略有不同,常数左右移位不会将右操作数对32取余,而变量的左右移会将右操作数对32取余。

2.左移均补0,有符号数的负数的右移补1,正数的右移补0。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: