【问题标题】:What is the best way to work around the fact that ALL Java bytes are signed?解决所有 Java 字节都已签名这一事实的最佳方法是什么?
【发布时间】:2010-09-05 21:09:17
【问题描述】:

在 Java 中,没有无符号字节这种东西。

处理一些低级代码时,有时您需要处理无符号值大于 128 的字节,这会导致 Java 将它们解释为负数,因为 MSB 用于符号。

有什么好的方法可以解决这个问题? (说不使用 Java 不是一种选择)

【问题讨论】:

    标签: java byte unsigned signed


    【解决方案1】:

    如果你这样做,实际上可以去掉 if 语句和加法。

    byte[] foobar = ..;
    int value = (foobar[10] & 0xff);
    

    这样,Java 不会将字节解释为负数,也不会翻转整数上的符号位。

    【讨论】:

    • 一个关于效率的小提示:当将上面的表达式编译成本地机器指令时,Java 的 Hotspot Client VM 将执行一个普通的字节到 int 提升(使用sign extension),然后是一个 AND 操作. Hotspot Server VM 足够聪明,可以通过零扩展进行促销,跳过 AND。
    【解决方案2】:

    从数组中读取任何单个值时,将其复制为类似 short 或 int 的形式,然后手动将负数转换为应为的正值。

    byte[] foobar = ..;
    int value = foobar[10];
    if (value < 0) value += 256 // Patch up the 'falsely' negative value
    

    写入数组时也可以进行类似的转换。

    【讨论】:

    • 做 int value=(foobar[10]&0xFF);
    • 也许吧,但我希望我的代码尽可能清晰和有启发性。另外,我不知道 '&' 在 Java 中对负整数有什么作用(至少在没有谷歌搜索的情况下不是这样),所以我玩得很安全。
    • 为什么会对负数做任何不同的事情。并且是一个布尔运算,它适用于单个位,它确实知道、检查或关心一个数字是正数、负数还是任何其他值。
    • 我认为也许 0xFF 会被视为有符号字节(即 -1),然后在传递之前将符号扩展为 32 位有符号整数(即给出 0xFFFFFFFF aka -1)作为 '&' 的参数。这将给出不正确的结果。从讨论中可以清楚地看出,Java 不会这样做,但我认为最好安全行事。
    【解决方案3】:

    使用 int 通常比使用 short 更好,因为 java 在内部无论如何都使用 32 位值(即使是字节,除非在数组中),因此使用 int 将避免字节码中不必要的与 short 值的转换。

    【讨论】:

    • 好吧,如果该值始终是一个字节(即 8 位),那么使用 byte 会更清晰,更好地传达代码的意图,所以我会使用它来提高可读性,甚至如果它使用与int 相同的空间。
    • 确实如此,尽管您在那里获得了额外的字节码来强制将值输入和输出字节,因此开销很小。可读性 > 虽然是微小的无形好处。
    • 此外,如果您碰巧依赖在某处使用 byte 的库(想到 Android 上的 USB 堆栈),意识到 int 更适合您的预期目的将无济于事。
    【解决方案4】:

    您最好的选择可能是使用整数而不是字节。它有空间允许大于 128 的数字,而无需创建特殊对象来替换字节的开销。

    这也是比我聪明的人(每个人)提出的建议

    【讨论】:

      【解决方案5】:

      进行位操作/无符号字节的最佳方法是使用 ints。即使它们是有符号的,它们也有大量的备用位(总共 32 个)可以视为无符号字节。此外,所有数学运算符都会将较小的固定精度数转换为 int。示例:

      short a = 1s;
      short b = 2s;
      int c = a + b; // the result is up-converted
      short small = (short)c; // must cast to get it back to short
      

      因此,最好只使用整数并将其屏蔽以获取您感兴趣的位。示例:

      int a = 32;
      int b = 128;
      int foo = (a + b) | 255;
      

      这里有更多关于 Java 原始类型的信息http://mindprod.com/jgloss/primitive.html

      最后一点,Java 中有一个无符号的固定精度数。这就是 char 原语。

      【讨论】:

        【解决方案6】:

        我知道这是一个很晚的回复,但我在尝试做完全相同的事情时遇到了这个帖子。问题只是试图确定 Java 字节是否 >127。

        简单的解决办法是:

        if((val & (byte)0x80) != 0) { ... }
        

        如果真正的问题是 >128,则只需向该 if 语句添加另一个条件即可。

        【讨论】:

          【解决方案7】:

          我想你可以只用一个短的来存储它们。效率不是很高,但除了我所见过的一些艰巨的努力之外,它确实是唯一的选择。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-06-20
            • 1970-01-01
            • 1970-01-01
            • 2010-11-08
            • 2021-12-25
            • 1970-01-01
            • 2010-10-11
            • 1970-01-01
            相关资源
            最近更新 更多