【问题标题】:How to use bitshifting in Java如何在 Java 中使用位移位
【发布时间】:2015-11-06 04:45:47
【问题描述】:

我正在尝试构建 IP 标头。

IP 标头具有以下字段:版本、IHL、DSCP 等。我想填充一个字节数组,以便可以以字节为单位存储信息。

然而,我感到困惑的是版本字段只有 4 位宽。 IHL 也只有 4 位宽。如何将这两个字段的值都表示为一个字节?我需要做位移吗?

例如版本 = 4,IHL = 5。我需要创建一个等于 0100 0101 = 45h 或十进制 69 的字节。

【问题讨论】:

    标签: java binary bit-manipulation packets


    【解决方案1】:
    (byte) (4 << 4) | 5
    

    这会将值 4 向左移动,然后将低 4 位设置为值 5。

    1. 00000100一个值(4)
    2. 01000000左移4位后(&lt;&lt; 4)
    3. 00000101 另一个值 (5)
    4. 01000101 #2 和 #3 按位或 (|) 的结果

    因为操作数是int 类型(即使它们是byte 值,当| 等运算符作用于它们时,它们也会被提升为int),最终结果需要转换为存储在byte

    如果您在任何按位运算中使用byte 值作为操作数,则隐式转换为int 可能会导致意外结果。如果您想将 byte 视为在该转换中未签名,请使用按位与 (&amp;):

    byte b = -128; // The byte value 0x80, -128d
    int uint8 = b & 0xFF; // The int value 0x00000080, 128d
    int i = b; // The int value 0xFFFFFF80, -128d
    int uintr = (b & 0xFF) | 0x04; // 0x00000084
    int sintr = b | 0x04; // 0xFFFFFF84
    

    【讨论】:

    • byte Version = 5; byte IHL = 4; byte b = (Version &lt;&lt; 4) + IHL; 编译良好,无需转换
    • 谢谢@Erickson - 很好的回答。
    • 在将整数引入答案之前,最好只使用顶部部分
    • 那为什么我可以编译没有错误,只使用字节而不进行转换?
    • 我应该使用什么编译器来测试这样的东西? byte b = (((byte)5) &lt;&lt; 4) + ((byte)4); System.out.println(b); 适用于 Oracle 的 JDK 8u65 for mac
    【解决方案2】:

    你可以这样做:

        int a = 0x04;
        a <<= 4;
        a |= 0x05;
        System.out.println(a);
    

    本质上是把 0b00000100 变成 0b01000000,然后变成 0b01000101。

    【讨论】:

      【解决方案3】:

      https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

      要在一个字节中创建一个包含版本和 IHL 的紧凑字段,请尝试这样做

      byte b = (byte)((Version << 4) + IHL);
      

      这仅适用于版本和国际人道法是 0 到 15 之间的数字

      【讨论】:

      • Type mismatch: cannot convert from int to byte
      • 我正在为 Version 和 IHL 使用字节,但没有收到错误
      • &lt;&lt; 实际上是可以的,但 + 执行二进制提升到 intlong,这取决于最宽的操作数。你在用什么编译?您可能想要切换,因为根据language specification,此代码无效
      • @erickson 可能就像 Debian 上两周大的 javac 和 java 版本(很确定它是 Debian)
      • 1.8.0_25-b17 说,error: incompatible types: possible lossy conversion from int to byte,1.7.0_67-b01 说error: possible loss of precision。 Eclipse 给出了我上面显示的消息。你也有来自 JLS 的引文。
      【解决方案4】:

      仅仅因为一个字节是 8 位,而您的值最多只能是 4,这不是问题。额外的 4 位将始终为零。

      所以如果你存储 1 例如:

      0000 0001

      或 15(这是最大值对吗?):

      0000 1111

      【讨论】:

      • 这样的疑惑应该在评论区解开。这不是答案
      • @FaizPinkman 有什么疑问?我给出了一个明确的答案,我不欣赏你的反对意见。我是说无论如何都将它存储为一个完整的字节。
      • 问题说明了如何将两个值放入一个字节中
      【解决方案5】:

      在 Java 中无法进行字节移位。

      How does bitshifting work in Java?

      但是,就逻辑而言,如果您希望将版本和 IHL 放在一个字节中,您可以使用以下方法来实现

      byte value = (byte) (IHL | VERSION << 4);
      

      【讨论】:

      • 您似乎将 Java 与其他语言混淆了,其中一个字符相当于一个字节。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 2011-03-19
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多