左移位负移位计数

时间:2011-02-09 13:48:19

标签: c

这里到底发生了什么?

a << -5

显然它并没有正确转变。但我读过的那本书指出:

  

在一台机器上,这个表达式实际上是左移27位

我的问题是;为什么?什么原因导致27位左移?在使用负移位计数换档时会发生什么?谢谢。

5 个答案:

答案 0 :(得分:68)

右侧的负整数是C语言中未定义的行为。

ISO 9899:2011 6.5.7逐位移位运算符:

  

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。 如果右操作数的值为负或大于或等于提升的左操作数的宽度,行为未定义

答案 1 :(得分:16)

正如其他成员已经回答的那样,它会产生未定义的行为。我想在这里提一下,你引用这本书(“在一台机器上”)似乎是偏袒的。它没有概括行为。该书也可能已经解释了该行为未按照标准定义。 顺便说一下,我刚刚通过“新C标准 - 经济和文化评论”并发现了这一说法:

  

Intel Pentium SAL指令   (由gcc和Microsoft生成   用于评估左移的C ++仅使用   转变的最后五位   量

这很好地解释了为什么左移-5可能导致左移27(对于2的补数表示负数)

答案 2 :(得分:11)

行为未定义。

在5位二进制算术中,二进制补码-5具有与无符号+27相同的二进制表示,这可能解释了该特定平台。

答案 3 :(得分:1)

如果您要移位的值是32位变量,则移位-5进入“循环”并向前移动27。转移只能以“无符号”的方式进行。

答案 4 :(得分:1)

int main()
{
    unsigned int a = 1;
    printf("%u\n",a<<(-1));
    return 0;
}

输出为2147483648。

这是我的假设和验证:(只是假设!)

1.“&lt;&lt;&lt;右操作数必须是unsigned int类型,

首先,(int)“-1”将被转换为(unsigned int)“ - 1”。原因int类型是二进制补码表示,结果将是2 ^ 32-1(unsigned int)

2.由于数字2 ^ 32-1大于最大位移数字,2 ^ 32 - 1将是mod 32,等于27

还尝试了其他一些nagetive右操作数,并且带有假定规则的手动计算结果与我的IDE的产品相同。

我试图找到一些支持性的官方文件,女巫可以证实我的假设是否正确。也许你可以告诉我。