为什么Java和C#有位移操作符?

时间:2010-10-01 04:56:32

标签: c# java low-level premature-optimization bit-shift

整数乘法(暂时忘记分裂)之间的差异是否仍然有利于转移?如果是这样,差异有多大?

它似乎只是一个低级别的优化,即使你想要它不应该是(C#/ Java)字节码编译器或jit在大多数情况下捕获它?

注意:我测试了C#的编译输出(使用gmcs Mono C#编译器版本2.6.7.0),即使乘以2的倍数,乘法示例也不使用shift进行乘法。

C# http://csharp.pastebin.com/hcrRnPrb

CIL http://csharp.pastebin.com/0js9F2c1

P.S。 我忘了在字节上使用它有多大帮助,但在使用它时仍然遇到一些麻烦。

8 个答案:

答案 0 :(得分:22)

第一个原因:

有时 - 大多数情况下 - 您希望将整数视为数字。有时虽然整数是表示一组位的便捷方式。

乘法是对数字的操作。

移位是对一组位的操作。

在乘法结果和移位结果之间恰好存在关系并不是特别相关。这些操作逻辑上不同。

第二个原因:

C#和Java都是为C开发人员所熟悉的,尽管是肤浅的。因此,来自C的常用习语包含在C#和Java中。

答案 1 :(得分:12)

如果我想将数字乘以4,我会写* 4。如果我的目的是左移一些位2位,我会写<< 2

回答问题:

  

为什么Java和C#有位移操作符?

我在二进制数据上做了很多工作,其中我没有考虑整数等 - 只是二进制 - 并且在那个区域中完全逻辑使用不断转移运营商。

当然,我可以输入* 2等,但我真正想要做的事情就是移位。

这在字节很重要的一系列领域很常见(例如图形编程,序列化等)。

此外,还有一些微妙的移位操作,其中希望它表现得像一个整数,特别是在处理边缘时......当你从地图左移一点,或者将右移到地图(-ve vs + ve等)时发生的事情的规则很好理解但很关键。同样,整数乘法的checked / unckecked行为有时非常重要。

答案 2 :(得分:8)

你是对的,如果移位运算符仅用作乘法的替代,它应该留给编译器。

我想你忽略了以下应用程序:

  • 加密/解密
  • CRC计算
  • 位图操作(图形,数据库锁定)
  • 压缩/解压缩
  • 设置硬件寄存器的数据
  • 更改编码

还有更多需要在没有本机代码的情况下进行高效实现。

答案 3 :(得分:1)

你所问的基本上不是C#/ Java中存在bithift运算符的原因,而是为什么javac编译器不会将乘法和除法与2的幂优化为位移。

对此的下意识反应是乘法和除法具有与位移不同的语义,因此它不会映射100%来替换操作。

此外,您忘记了JIT(HotSpot)中发生的额外编译步骤,其中发生了各种其他优化。坦率地说,没有必要优化这个特定的步骤,而不是C代码就像编译器生成它一样。

答案 4 :(得分:0)

因为语言设计师认为拥有它们会很好。

它们与其他一些操作相当并不重要,并且编译器足够聪明以有效地实现操作。如果那就是我们要去的地方,那么除了宏汇编程序和非常好的链接时优化器之外,你可能需要的不仅仅是带有垃圾收集器的虚拟机。这些不是语言设计师通常追求的目标。

答案 5 :(得分:0)

例如,您的程序可能会使用像位掩码之类的东西。在那种情况下,位移操作是必要的。或者,如果您只是在解决一些需要以指定方式编码状态的奇怪任务。

观看此tutorial - 大多数样本来自数学问题。如果你只是制作一个网站或一个GUI应用程序,你可能不需要转移,但有时你真的这样做......

答案 6 :(得分:0)

这样你就可以左右移位。你希望那些位和它们的移位操作代表什么完全取决于你。

答案 7 :(得分:0)

除了其他原因之外,还有很多情况下您可能需要转移(或其他位操作)以通过网络与第三方库或远程应用程序进行交互。