Сдвиг битов - почему этот код использует сдвиг вправо 24, 16 и 8? - PullRequest
0 голосов
/ 04 февраля 2019

Я смотрю на этот код 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
}

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Если у вас есть 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)

Кодирование с прямым порядком байтов - это то место, куда вы отправляете старший байтво-первых, вам нужны биты 24-31 в первом байте, биты 16-23 во втором байте и так далее.Стандартный порядок байтов для сетевых коммуникаций имеет порядок байтов.( 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)

0 голосов
/ 04 февраля 2019

Это просто упаковка 4 байтов 32-битного целого числа в 4 последовательных байта, с осторожностью при использовании определенного порядка байтов (в данном случае это 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 битов.

Итак, еще раз: это просто реализует префикс длины с прямым порядком байтоврамы.Получающий код обратит это путем сдвига влево и / или для восстановления длины из первых 4 байтов.

...