【问题标题】:Issues when converting bytes to integers (Java specific?)将字节转换为整数时的问题(Java 特定?)
【发布时间】:2012-12-07 19:00:16
【问题描述】:

我对从字节到整数的转换有点困惑。考虑以下代码:

byte[] data = new byte[] { 0, (byte) 0xF0 };

int masked = data[0] << 8 & 0xFF | data[1] & 0xFF; //240
int notMasked = data[0] << 8 | data[1]; //-16

因为 java 中的字节是有符号的,data[1] 不是十进制的 240,而是 2 的补码,-16。但是,它仍然应该是二进制:0x11110000 那么,为什么我需要这样做 data[1] &amp; 0xFF

在将所有内容传递给| 运算符之前,Java 是否会将所有内容都转换为整数?那么为什么&amp;0xFF 会有所作为呢?

【问题讨论】:

  • 前段时间我做了一些代码的 C 到 Java 的移植,它使用了大量的按位运算,并想出了一个 helper class 让事情变得更容易一些。无法保证这些产品的质量或效率,但它们为我完成了这项工作。

标签: java binary


【解决方案1】:

Java 字节是有符号的(不幸的是) - 因此,当您将值提升为 int 以执行按位 | 时,它最终会被符号扩展为 0xFFFFFFF0。然后将|data[0] 混淆。 &amp; 0xff 的掩码将其转换为整数值 240(只是 0x000000F0)。

但是,您仍然遇到了问题。这段代码:

int masked = data[0] << 8 & 0xFF | data[1] & 0xFF;

应该是:

int masked = ((data[0] & 0xff) << 8) | (data[1] & 0xFF);

... 否则,您将在 轮班之后屏蔽,这是行不通的。我添加了括号,因为我不确定&amp;&lt;&lt;| 的优先级...

【讨论】:

  • 啊哈!所以|&amp; 都提升为整数,所以&amp;0xFF 发生整数值。这完全解释了它,非常感谢!
  • @Miquel: &amp; 0xFF 升级到 int,所以 | 不必这样做,如果你明白我的意思 :)
  • 跟进:这当然是 Java 特有的,但其他语言也这样做吗?
  • 是的。不错的问题。谢谢!
  • @Miquel:我不了解所有语言。例如,在 C# 中,byte 是未签名的,因此不会出现问题。不过请查看我的编辑 - 我认为您的代码仍然存在问题。
【解决方案2】:

类似于已知的“谜题”

byte x = -1;
x = x >>>= 1;
System.out.println(x);

生产

-1

没有班次?这是因为在编译算术/移位/比较表达式之前,javac 会将 byte(以及 short 和 char)提升为 int 或 long(如果表达式中有 long),所以它的工作方式如下

x -> int = 0xFFFFFFFF; 0xFFFFFFF >>> 1 = 0x7FFFFFF; (byte)0x7FFFFFF -> 0xFF

【讨论】:

  • 很好 :) 但是没有人会感到困惑:你在这里玩的是带符号的移位运算符 (&gt;&gt;&gt;) 而不是普通的 (&gt;&gt;)
  • 嗯,我认为>>> 被称为无符号,否则就没有谜题了,是吗?
猜你喜欢
  • 2019-09-15
  • 2010-12-28
  • 2017-01-30
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2016-01-10
  • 2013-09-27
相关资源
最近更新 更多