如何在 Java 中使用移位

How to use bitshifting in Java

我正在尝试构建 IP header。

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

然而,令我感到困惑的是 Version 字段只有 4 位宽。国际人道法也只有 4 位宽。我如何将这两个字段的值都表示为一个字节?我需要进行位移吗?

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

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

因此,如果您要存储 1,例如:

0000 0001

或15(哪个是最大值对吧?):

0000 1111

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

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

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

仅当 Version 和 IHL 是 0 到 15 之间的数字时才有效

你可以这样做:

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

基本上将 0b00000100 变成 0b01000000,然后变成 0b01000101。

Java 中无法进行字节移位。

How does bitshifting work in Java?

但是,就逻辑而言,如果你想要一个字节的版本和国际人道法,你可以使用下面的方法

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

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

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

因为操作数是 int 类型(即使它们是 byte 值,当像 | 这样的运算符作用于它们时,它们也会被提升为 int ), 最终结果需要一个cast存储在byte.

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

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