今天早上,ssjjll问了我位操作的问题。 我本来以为很easy,但是程序的输出总是不尽如人意。 我开始觉得是编译器的错误,但看了文件夹后才知道是自己学业不完善,实力不足造成的。 失望! 我一直以为完全掌握了C,C也到了七八重境界,没想到今天也在阴沟里翻船了。 记住,别忘了瓜的耻辱!
我们先看看有问题的代码。 int a=32;
int x=0xFFFFFFFF;
coutint(0xffffffff32 ) endl;
计数输入(x32 )结束;
coutint(0xffffffffa ) endl;
输出: VC 7.1调试为0,-1,-1.版本为0,0,0 .疑点: sizeof(int )==4。 因此,我认为向左移动32位后,int变量应该清除为0。 但是,输出结果不一致。 更不可思议的是,调试/发行版的输出也不同。 我推测这是一个应该把int变成无符号int的问题。 (直觉是有道理的,但我知道这不是问题的关键。 将所有程序更改为unsignedint,不更改输出! 也就是说:
将unsigned0xFFFFFFFF向右移动32次,居然也能得到0xFFFFFFFF! 更加不能接受了。
解答:
仔细观察c/c标准和MSDN,原因是我对位移操作的理解不足。
1 .所有移位操作的右操作数必须小于左操作数的位长,否则不定义结果。
2 .右移操作相对于unsigned系列,高位一直补0。 signed系列时,排名靠前的补记位。
3 .在操作过程中,可能会发生集成升级。 这很复杂。 c中采用与c相同的策略,提升后的量始终“有价值”,即原始bit值不变; 但是,不一定是“保号的”。 在运算中,如果char/bit field不能保留所有值,则将其提升为int类型;如果int也不能保留所有值,则将其提升为unsigned。 有几个罕见的情况。 值的保持和保证的运算是不同的值。
(1)、(、(、)、()、)、)=运算依赖于符号,在应用时可能导致不同的结果。 (2),=运算有时依赖于符号位。 )3)函数重载参数可能依赖于符号。
因此,上述程序的位操作次数在整数位数以上,输出结果不确定也是正常的。 为了完全理解这个问题,进行了以下实验: int a=31;
int x=0xFFFFFFFF;
couttypeid(0xfffffff ).name ) endl;
couttypeid(0x0fffffff ).name ) endl;
coutint(0xffffffff31 ) endl;
计数输入(x31 )结束;
coutint(0xffffffffa ) endl;
输出:在调试/发布中均为unsigned int,int,1,- 1,1
在这里,因为可以清楚地看到0xFFFFFFFF内的内容放置在未指定的int上,所以它的类型是未指定的int; 另一方面,0x0FFFFFFF可以在一个int中放置,所以类型为int。 两个一的输出什么也不说。 -1的输出中,x为有符号的整数,且符号比特为1,所以即使在高位比特中追加1,结果也始终不变。 但是,这1和-1的区别确实很模糊。
总结经验,对变量进行移位操作时,逻辑上应尽可能使用无符号数。 位移的长度请控制在字的长度以内。