这里到底发生了什么?
a << -5
显然它并没有正确转变。但我读过的那本书指出:
在一台机器上,这个表达式实际上是左移27位
我的问题是;为什么?什么原因导致27位左移?在使用负移位计数换档时会发生什么?谢谢。
答案 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的产品相同。
我试图找到一些支持性的官方文件,女巫可以证实我的假设是否正确。也许你可以告诉我。