左移,负移计数

这里到底发生了什么?

a << -5

很明显它没有正确的转变,但是我正在读的这本书说:

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

我的问题是,为什么?是什么导致了27位的左移?如果换挡时换挡次数为负,会发生什么情况呢?谢谢你。

63769 次浏览

这种行为是不明确的。

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

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

ISO9899:20116.5.7位移操作符:

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

如果你移动的值是一个32位变量,移动 -5进入一个“循环”并向前移动27。转移只能以“未签名”的方式进行。

正如其他成员国已经回答的那样,它产生了未定义行为。我想在这里提到的是,你从书中引用(“在一台机器上”)似乎是片面的。它没有概括这种行为。这本书可能还解释说,行为是未定义的,根据标准。 顺便说一句,我刚刚浏览了“新 C 标准——经济和文化评论”,发现了这句话:

英特尔奔腾 SAL 指令 (由 gcc 和 Microsoft C + + 用于评估左移)只使用 倒数五位 金额

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

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

输出是2147483648。

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

1. “ < <”右操作数必须是无符号 int 类型,

因此,首先,(int)“-1”将被强制转换为(unsignedint)“-1”。因为 int 类型是2的补数表示,结果是2 ^ 32-1(无符号 int)

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

也试过了一些其他负的右操作数数字,和手动计算结果与假定的规则将是相同的产品由我的 IDE。

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