3

我在看 F# doc on bitwise ops:

按位右移运算符。结果是第一个操作数的位右移了第二个操作数中的位数。从最低有效位置移出的位不会旋转到最高有效位置。对于无符号类型,最高有效位用零填充。对于有符号类型,最高有效位用 1 填充。第二个参数的类型是 int32。

与 MSB 用零填充的 C++ 语言(可能还有 C)相比,这种设计选择背后的动机是什么?例如:

int mask = -2147483648 >> 1; // C++ code

其中-2147483648 =

10000000 00000000 00000000 00000000

掩码等于 1073741824

其中 1073741824 =

01000000 00000000 00000000 00000000

现在,如果您在 F#(或 C#)中编写相同的代码,这确实会用一个填充 MSB,您将得到 -1073741824。

其中-1073741824 =

11000000 00000000 00000000 00000000
4

2 回答 2

6

有符号移位具有很好的特性,即将 x 右移 n 对应于 floor(x/2 n )。

在 .NET 上,两种操作都有 CIL 操作码(shr执行有符号移位和shr.un无符号移位)。F# 和 C# 根据要移动的类型的符号来选择要使用的操作码。这意味着如果您想要其他行为,您只需要在移位之前和之后执行数字转换(由于数字在 CLR 上的存储方式,这实际上对运行时没有影响 - 堆栈上的 int32 与 uint32 无法区分) .

于 2010-09-29T22:12:59.817 回答
5

要回答改革后的问题(在评论中):

C 和 C++ 标准没有定义右移负值的结果(它要么是实现定义的,要么是未定义的,我不记得是哪个)。

这是因为该标准被定义为反映底层指令集的最低公分母。例如,如果指令集不包含asr原语,则执行真正的算术移位需要几条指令。由于该标准要求一个两个的补码表示这一事实更加复杂。

于 2010-09-29T22:02:52.933 回答