简体   繁体   English

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

[英]What's the reason high-level languages like C#/Java mask the bit shift count operand?

This is more of a language design rather than a programming question. 这更多的是语言设计而不是编程问题。

The following is an excerpt from JLS 15.19 Shift Operators : 以下是JLS 15.19移位运算符的摘录:

If the promoted type of the left-hand operand is int , only the five lowest-order bits of the right-hand operand are used as the shift distance. 如果左侧操作数的提升类型是int ,则只使用右侧操作数的五个最低位作为移位距离。

If the promoted type of the left-hand operand is long , then only the six lowest-order bits of the right-hand operand are used as the shift distance. 如果左侧操作数的提升类型很long ,则只使用右侧操作数的六个最低位作为移位距离。

This behavior is also specified in C# , and while I'm not sure if it's in the official spec for Javascript (if there's one), it's also true based on my own test at least. 这种行为也在C#中指定 ,虽然我不确定它是否在Javascript的官方规范中(如果有的话),但至少基于我自己的测试也是如此。

The consequence is that the following is true: 结果是以下情况属实:

(1 << 32) == 1

I understand that this specification is probably "inspired" by the fact that the underlying hardware only takes 5 bits for the count operand when shifting 32-bit values (and 6 bits for 64-bit), and I can understand such behavior specified at the JVM level for example, but why would high level languages such as C# and Java retain this rather low-level behavior? 据我所知,这个规范很可能受到以下事实的启发:当移位32位值(64位为6位)时,底层硬件只占用计数操作数的5位,我可以理解在例如,JVM级别,但为什么高级语言(如C#和Java)会保留这种相当低级别的行为? Shouldn't they provide a more abstract view beyond the hardware implementation and behave more intuitively? 它们不应该提供超出硬件实现的更抽象的视图,并且行为更直观吗? (Even better if they can take a negative count to mean to shift in the OTHER direction!) (如果他们可以采取负数来表示向其他方向转移,那就更好了!)

Java and C# are not fully "high-level". Java和C#并不完全是“高级”。 They try real hard to be such that they can be compiled into efficient code, in order to shine in micro-benchmarks. 他们努力尝试将它们编译成有效的代码,以便在微基准测试中发挥作用。 This is why they have the "value types" such as int instead of having, as default integer type, true integers, which would be objects in their own right, and not limited to a fixed range. 这就是为什么他们有“值类型”如int而不是默认整数类型的真实整数,它们本身就是对象,而不仅限于固定范围。

Hence, they mimic what the hardware does. 因此,它们模仿硬件的功能。 They trim it a bit, in that they mandate masking, whereas C only allows it. 他们修剪了一下,因为他们要求掩盖,而C只允许它。 Still, Java and C# are "medium-level" languages. Java和C#仍然是“中级”语言。

Because in most programming environments an integer is only 32 bits. 因为在大多数编程环境中,整数只有32位。 So then 5 bits (which is enough to express 32 values) is already enough to shift the entire integer. 那么5位(足以表示32个值)已足以移动整个整数。 A similar reasoning exists for a 64bit long: 6 bits is all you need to completely shift the entire value. 对于64位长的存在类似的推理:只需要6位就可以完全移动整个值。

I can understand part of the confusion: if your right-hand operand is the result of a calculation that ends up with a value greater than 32, you might expect it to just shift all the bits rather than apply a mask. 我可以理解部分混淆:如果你的右手操作数是计算结果大于32的结果,你可能会期望它只是移位所有位而不是应用掩码。

C# and Java define shifting as using only the low-order bits of the shift count as that's what both sparc and x86 shift instructions do. C#和Java将移位定义为仅使用移位计数的低位,因为sparc和x86移位指令都是如此。 Java was originally implemented by Sun on sparc processors, and C# by Microsoft on x86. Java最初由Sun在sparc处理器上实现,而C#由Microsoft在x86上实现。

In contrast, C/C++ leave as undefined the behavior of shift instructions if the shift count is not in the range 0..31 (for a 32 bit int), allowing any behavior. 相反,如果移位计数不在0..31范围内(对于32位int),则C / C ++保留未定义移位指令的行为,允许任何行为。 That's because when C was first implemented, different handware handled these differently. 那是因为当C首次实施时,不同的手工具有不同的处理方式。 For example, on a VAX, shifting by a negative amount shifts the other direction. 例如,在VAX上,移动负量会移动另一个方向。 So with C, the compiler can just use the hardware shift instruction and do whatever it does. 因此,使用C,编译器可以只使用硬件移位指令并执行任何操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM