右移位操作中的意外输出

时间:2014-09-17 17:35:17

标签: c bit-manipulation bitwise-operators

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位时,为什么输出不同?

1 个答案:

答案 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在结果类型中可表示,即   结果价值;否则,行为未定义。