int main()
{
int x = 0xff0000ff;
int N_BITS = sizeof (int) * 8; /* 32 */
int l = 0x0;
printf ("Right shift expected result: %x\n", 0x80000000 >> (31));
l = (x & (0x00000001 << (N_BITS - 1)));
printf ("l = %x\n", l);
/* Right Shift l by 31 bits */
l = l >> 31;
printf ("l after right shift by 31 bits: %x\n", l);
}
~
输出:
Right shift expected result: 1
l = 80000000
l after right shift by 31 bits: ffffffff
〜
0x80000000右移31位应该导致0x00000001,如第一个输出所示。当变量l
向右移位31位时,为什么输出不同?
答案 0 :(得分:3)
假设
的结果l = (x & (0x00000001 << (N_BITS - 1)));
是0x80000000
(见下文无法保证,因为表达式会调用未定义的行为)。
在二进制补码系统中,0x80000000
为负值({{1}})。
INT_MIN
C表示此l = l >> 31;
操作是实现定义的。在您的系统中,它执行符号扩展:传播符号位。
(C11,6.5.7p4)“如果E1有一个带符号的类型和一个负值,那么 结果值是实现定义的。“
最后说明原因:
>>
调用未定义的行为。
从马口(强调我的):
(C11,6.5.7p4)“E1&lt; E2的结果是E1左移E2位位置;空位用零填充。如果E1有无符号类型,则结果的值为E1 ×2 ^^ E2,减少模数 比结果类型中可表示的最大值多一个。 如果E1已签名 类型和非负值,E1×2 ^^ E2在结果类型中可表示,即 结果价值;否则,行为未定义。“