C#/ Java等高级语言掩盖位移计数操作数的原因是什么?

时间:2010-02-22 14:31:49

标签: java c# bit-manipulation language-design bit-shift

这更多的是语言设计而不是编程问题。

以下摘自JLS 15.19 Shift Operators

  

如果左侧操作数的提升类型为int,则只使用右侧操作数的五个最低位作为移位距离。

     

如果左侧操作数的提升类型为long,则只使用右侧操作数的六个最低位作为移位距离。

此行为也是specified in C#,虽然我不确定它是否符合Javascript的官方规范(如果有的话),但至少基于我自己的测试也是如此。

结果是以下情况属实:

(1 << 32) == 1

据我所知,这个规范很可能受到这样一个事实的启发:当移位32位值时,底层硬件只占用计数操作数的5位(64位为6位),我可以理解这种行为例如,在JVM级别指定,但为什么高级语言(如C#和Java)会保留这种相当低级别的行为?它们不应该提供超出硬件实现的更抽象的视图,并且行为更直观吗? (如果他们可以采取负数来表示向其他方向转移,那就更好了!)

3 个答案:

答案 0 :(得分:8)

Java和C#并非完全“高级”。他们努力尝试将它们编译成有效的代码,以便在微基准测试中发挥作用。这就是为什么他们有“值类型”,例如int,而不是默认整数类型,真正的整数,它们本身就是对象,而不仅限于固定范围。

因此,他们模仿硬件的作用。他们修剪了一下,因为他们要求掩盖,而C只允许它。 Java和C#仍然是“中级”语言。

答案 1 :(得分:5)

因为在大多数编程环境中,整数只有32位。那么5位(足以表示32个值)已足以移动整个整数。对于64位长的存在类似的推理:只需6位即可完全移动整个值。

我可以理解部分混淆:如果你的右手操作数是计算结果大于32的结果,你可能会期望它只是移位所有位而不是应用掩码。 / p>

答案 2 :(得分:5)

C#和Java将移位定义为仅使用移位计数的低位,因为sparc和x86移位指令都是如此。 Java最初由Sun在sparc处理器上实现,而C#由Microsoft在x86上实现。

相反,如果移位计数不在0..31范围内(对于32位int),则C / C ++保留未定义移位指令的行为,允许任何行为。那是因为当C首次实施时,不同的手工具有不同的处理方式。例如,在VAX上,移动负量会移动另一个方向。因此,使用C语言,编译器只需使用硬件移位指令即可完成任务。