Что такое 0xFF и почему оно сдвинуто 24 раза? - PullRequest
5 голосов
/ 30 октября 2010
#define SwapByte4(ldata) \
   (((ldata & 0x000000FF) << 24) | \
   ((ldata & 0x0000FF00) << 8) | \
   ((ldata & 0x00FF0000) >> 8) | \
   ((ldata & 0xFF000000) >> 24))

Что это за 0x000000FF? Я знаю, что десятичное 15 представлено в шестнадцатеричном виде как F, но почему это << 24? </p>

Ответы [ 4 ]

32 голосов
/ 30 октября 2010

Вот шестнадцатеричное значение 0x12345678, записанное в двоичном формате и аннотированное некоторыми битовыми позициями:

|31           24|23           16|15            8|7         bit 0|
+---------------+---------------+---------------+---------------+
|0 0 0 1 0 0 1 0|0 0 1 1 0 1 0 0|0 1 0 1 0 1 1 0|0 1 1 1 1 0 0 0|
+---------------+---------------+---------------+---------------+

... а вот 0x000000FF:

+---------------+---------------+---------------+---------------+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|1 1 1 1 1 1 1 1|
+---------------+---------------+---------------+---------------+

побитовое И выбирает только нижние 8 битов исходного значения:

+---------------+---------------+---------------+---------------+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 1 1 1 1 0 0 0|
+---------------+---------------+---------------+---------------+

... и сдвигая его влево на 24 бита, перемещает его из нижних 8 битов в верхнее:

+---------------+---------------+---------------+---------------+
|0 1 1 1 1 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|
+---------------+---------------+---------------+---------------+

... что составляет 0x78000000 в шестнадцатеричном формате.

Другие части работают с оставшимися 8-битными частями ввода:

0x12345678
& 0x000000FF
  ----------
  0x00000078 << 24 = 0x78000000       (as shown above)

  0x12345678
& 0x0000FF00
  ----------
  0x00005600 <<  8 = 0x00560000

  0x12345678
& 0x00FF0000
  ----------
  0x00340000 >>  8 = 0x00003400

  0x12345678
& 0x00000000
  ----------
  0x12000000 >> 24 = 0x00000012

                   | ----------
                     0x78563412

, поэтому общий эффект заключается в рассмотрении 32-битное значение ldata как последовательность из четырех 8-битных байтов и обратный порядок.

5 голосов
/ 30 октября 2010

Этот код обычно используется для переключения между форматами с прямым и младшим порядком .Существует также небольшая хитрость, которая преобразует слово в каком-то известном формате (скажем, с прямым порядком байтов) в любой порядок байтов, используемый текущей машиной, и наоборот.Это будет выглядеть примерно так:

unsigned long littleEndian;
unsigned char* littleBytes = &littleEndian;
unsigned long result = 0;
for (i = 0; i < 4; i++)
    result += unsigned long(littleBytes[i]) << (8 * i);

Это работает (при условии, что я не испортил это), потому что независимо от того, как на самом деле хранятся байты, сдвиг влево гарантированно сместится в сторону более значимых бит.Преобразование в символ * позволяет получить доступ к байтам в порядке их фактического хранения в памяти.Используя этот трюк, вам не нужно обнаруживать машинный порядок чтения / записи в известном формате.По общему признанию Вы могли также просто использовать стандартные функции (hton и т. Д.): P

(Примечание: Вы должны быть немного осторожны и бросить чар перед смещением, иначе это просто переполняет все Ваши ботинки. Также,+ = не единственный вариант, | =, вероятно, имеет больше смысла, но может быть менее понятным, если вы к этому не привыкли, я не уверен)

2 голосов
/ 30 октября 2010

Вы должны рассматривать 0x000000FF как битовую маску, то есть, где это 1, будет взято значение ldata, а где 0 - 0.

Чтобы понять битовую маску, вам нужно преобразовать ее в двоичную, с шестнадцатеричным кодом это очень просто, каждое шестнадцатеричное число равно 4 двоичным цифрам, т.е.

hex 0 = двоичный 0000 hex 1 = двоичный 0001 и т. д.

Теперь о сменах: обратите внимание, что сдвиг берет некоторые данные из источника, ровно 8 бит, и перемещает их в другое место назначения.

Теперь обратите внимание, что есть |, т. Е. Операция ИЛИ для всех операций с битовой маской И, т. Е. Нули останутся равными нулю, а в случае '1' результат будет содержать единицу.

Надеюсь, это поможет:)

0 голосов
/ 30 октября 2010

Допустим, данные представляют собой 32-битное число, представленное как 0x12345678 (каждое число - 4 бита в шестнадцатеричном формате)

Данные & 0x000000FF означают, что сохраняются только последние 8 бит (называемых битовой маской) = 0x00000078

<< 24 означает перемещение этого значения влево на 24 бита (78 начинается с позиции 24 [0 index]) = 0x78000000 </p>

The |означает логический или который в этом случае будет просто сложением

Конечный результат = 0x78563412

Читайте о логических манипуляциях

...