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

pol*_*nts 16 c# java bit-manipulation language-design bit-shift

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

以下是JLS 15.19移位运算符的摘录:

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

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

这种行为也在C#中指定,虽然我不确定它是否在Javascript的官方规范中(如果有的话),但至少基于我自己的测试也是如此.

结果是以下情况属实:

(1 << 32) == 1
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*nin 8

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

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


Joe*_*orn 5

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

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


Chr*_*odd 5

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

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