移位 - 为什么此代码使用 24、16 和 8 右移?

Bit Shifting - Why is this code using 24, 16, and 8 right shift?

我正在查看这段 java 代码并试图理解它。除了移位部分,我了解它的所有内容。

我知道下面使用位移位的代码正在构建一些值来填充字节[],但我不知道为什么它特别使用右移,为什么是 24 位,然后是 16 位,然后是 8 位?为什么选择这些值而不是其他值?

private void Send(NetSocket out, int MsgID, byte MsgSeq, char MsgLetter, String data) 
{
    int msglen = data.length() + 2; 
    byte[] msg = new byte[msglen + 8];
    byte[] md = data.getBytes();
    msg[0] = (byte) (msglen >> 24);
    msg[1] = (byte) (msglen >> 16);
    msg[2] = (byte) (msglen >> 8);
    msg[3] = (byte) (msglen);
    msg[4] = (byte) (MsgID >> 24);
    msg[5] = (byte) (MsgID >> 16);
    msg[6] = (byte) (MsgID >> 8);
    msg[7] = (byte) (MsgID);
    msg[8] = (byte) MsgLetter;
    msg[9] = MsgSeq;
    System.arraycopy(md, 0, msg, 10, msglen - 2);

    // send
}

这只是将一个 32 位整数的 4 个字节打包成 4 个连续的字节,注意使用特定的字节序(在本例中为大字节序)。它只是说:

// put the "biggest" 8 bits into the first byte,
// by right shifting the value 24 bits
msg[0] = (byte) (msglen >> 24);

将一个 32 位整数右移 24 位意味着您在 最低 8 个重要位置中剩下 8 个最高有效位,准备打包成 byte.接下来的 3 行处理接下来的 8 位(右移 16),然后是下一个(右移 8)等。

转换为 byte 简单地 丢弃 除了最低有效 8 位之外的所有内容,因此在每次移位后(或最后一个移位缺失),我们取 32 位的四分之一。

再说一遍:这只是实现了帧的大端长度前缀。接收代码将通过左移和 or-ing 来反转它,以从前 4 个字节重建长度。

如果你有一个 32 位整数,你可以把它当作四个 8 位整数:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01
\---------------------/ \---------------------/ \---------------------/ \------------------/
  bits 24-31 (8 bits)     bits 16-23 (8 bits)      bits 8-15 (8 bits)     bits 0-7 (8 bits)

Big-endian 编码是首先发送最高有效字节的位置,因此您需要第一个字节中的第 24-31 位,第二个字节中的第 16-23 位,等等。网络通信的标准字节顺序是 big-endian。 (Little-endian 是相反的方式,通常用于 x86 和其他一些平台上的内存存储。)

如果将整数转换为字节,最重要的 位将被丢弃。

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01
\---------------------/ \---------------------/ \---------------------/ \------------------/
  bits 24-31 (8 bits)     bits 16-23 (8 bits)      bits 8-15 (8 bits)     bits 0-7 (8 bits)


             cast to (byte)
                                                                        07 06 05 04 03 02 01
                                                                        \------------------/
                                                                          bits 0-7 (8 bits)

如果你右移,你将这些位移动过来,这样你就可以转换为(byte)并连续获得32位整数的其他部分:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01
\---------------------/ \---------------------/ \---------------------/ \------------------/
  bits 24-31 (8 bits)     bits 16-23 (8 bits)      bits 8-15 (8 bits)     bits 0-7 (8 bits)
          |
          \---------------------------- >> 24 -----------------------------------\
                                                                                 |
                                                                        07 06 05 04 03 02 01
                                                                        \------------------/
                                                                        previously bits 24-31
                                                                        now bits 0-7 (8 bits)