关于Integral Promotions

 

节选自:http://www.cnitblog.com/guopingleee/archive/2009/01/18/53849.html

 

 

1. 所有的位移操作的右操作数必须小于左操作数的位长度,否则结果未定义
2. 右移操作对于unsigned系列,高位一直补0。对于signed系列,高位补符号位
3. 在操作过程当中,有可能产生Integral Promotions。这就比较复杂了。C++中采用和C相同的策略,提升后的的量总是“保值的”,即原有的bit值不变;但不一定是“保号的”。运算中,如果char/bit field不能保持全部的值,就会被提升到int型,如果int也不能保存全部的值就会被提升至unsigned。有几种罕见的情况,保值和保号的运算会导致不同的值: 
(1) /, %, /=, %=, <, <=, >, >=
 运算依赖于符号,应用时可能导致不同结果。
(2)>>, >>= 运算有时依赖于符号位。
(3)函数重载参数可能依赖于符号。

由此可见,上述程式的位操作次数大于等于了整数的位数,输出结果不确定也是正常的。为了完全理解这个问题,再作下面的试验:

 int a = 31;
 int x = 0xFFFFFFFF;
 cout << typeid(0xFFFFFFFF).name() << endl;
 cout << typeid(0x0FFFFFFF).name() << endl;
 cout << int(0xFFFFFFFF >> 31) << endl;
 cout << int(x >> 31) << endl;
 cout << int(0xFFFFFFFF >> a) << endl;

输出:Debug/Release下均为 unsigned int, int, 1, -1, 1
这里能清晰地看到
0xFFFFFFFF之内被unsigned int放下,所以其类型是unsigned int;而0x0FFFFFFF一个int就能放下了,所以类型是int。两个1的输出没什么好说的。-1的输出是因为x为有符号数,且符号位是1,所以高位补1,结果总不变。但这个1和-1的差异的确够隐晦的。

总结经验:当对变量进行位移操作时,逻辑上应该尽可能使用无符号数。位移长度应严格控制在字长以内。

你可能感兴趣的:(关于Integral Promotions)