为什么这段代码使用24、16和8右移?

tpxzln5u  于 2021-07-12  发布在  Java
关注(0)|答案(2)|浏览(350)

我正在看这个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
}
syqv5f0l

syqv5f0l1#

如果您有一个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)
mrphzbgm

mrphzbgm2#

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

// 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位中的四分之一。
同样:这只是实现了一个帧的大端长度前缀。接收代码将通过左移和/或ing来反转,以从前4个字节重建长度。

相关问题