Что 0x01 и 0x80 представляют в C побитовых операциях? - PullRequest
5 голосов
/ 18 апреля 2010

Я пытаюсь изменить порядок битов в C (домашнее задание, тема: побитовые операторы). Я нашел это решение, но меня немного смущают используемые шестнадцатеричные значения - 0x01 и 0x80.

  unsigned char reverse(unsigned char c) {
     int shift;
     unsigned char result = 0;

     for (shift = 0; shift < CHAR_BITS; shift++) {
        if (c & (0x01 << shift))
            result |= (0x80 >> shift);
     }
     return result;
  }

Книга 1007 *, над которой я работаю, не обсуждала такого рода ценности, поэтому я не совсем уверена, что с ними делать. Может кто-нибудь пролить свет на это решение? Спасибо!

Ответы [ 4 ]

4 голосов
/ 18 апреля 2010

0x01 - это младший значащий бит, следовательно, десятичное значение равно 1.

0x80 - самый значимый бит из набора 8-битных байтов. Если он хранится в подписанном символе (на машине, которая использует нотацию с дополнением до 2 - как это может ожидать большинство машин), это наиболее отрицательное значение (десятичное -128); в беззнаковых символах - десятичное число + 128.

Другой шаблон, который становится второй натурой - это 0xFF со всеми установленными битами; это десятичное значение -1 для знаков со знаком и 255 для знаков без знака. И, конечно, есть 0x00 или ноль без установленных битов.

То, что делает цикл в первом цикле, - это проверка, установлен ли младший бит (младший значащий бит), и, если он установлен, задает старший бит (младший значащий бит) в результате. В следующем цикле он проверяет следующий за LSB и устанавливает следующий за MSB и т. Д.

| MSB |     |     |     |     |     |     | LSB |
|  1  |  0  |  1  |  1  |  0  |  0  |  1  |  1  |   Input
|  1  |  1  |  0  |  0  |  1  |  1  |  0  |  1  |   Output
|  1  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |   0x80
|  0  |  0  |  0  |  0  |  0  |  0  |  0  |  1  |   0x01
|  0  |  1  |  0  |  0  |  0  |  0  |  0  |  0  |   (0x80 >> 1)
|  0  |  0  |  0  |  0  |  0  |  0  |  1  |  0  |   (0x01 << 1)
3 голосов
/ 18 апреля 2010

Каждая шестнадцатеричная цифра представляет 4 бита, поэтому

  • 0x01 - это длинный путь написания 1.
  • 0x80 - это короткий способ записи в двоичном формате [1000] [0000] или 128.

Решение использует побитовые операторы для проверки и установки значений.

Выражение:

if (a & b) { ... }

выполняет «...», если один и тот же бит равен 1 как в «a», так и в «b».

Выражение

c |= b

устанавливает биты в 'c' в 1, если они равны 1 в 'b'.

Цикл перемещает тест и устанавливает бит вниз по линии.

Удачи!

1 голос
/ 04 мая 2019

Значения 0x01 и 0x80 специально записаны в шестнадцатеричной записи, чтобы подчеркнуть их значимость как наименее значимых и наиболее значимых битов типа unsigned char.

И все же автор допустил несколько ошибок:

  • макрос CHAR_BITS написан с ошибкой: он должен быть CHAR_BIT.
  • использование CHAR_BIT вместо жесткого кодирования почти универсального значения 8 является ценным усилием для полной переносимости, однако это усилие сводится на нет использованием 0x80, которое допустимо только в том случае, если CHAR_BIT == 8.
  • есть еще одна тонкая проблема переносимости: 0x01 << shift будет иметь неопределенное поведение для shift = CHAR_BIT-1 на платформе, где sizeof(unsigned char) == sizeof(int), потому что 0x01 имеет тип int (а не unsigned int, нелогично, не так ли ?).

Вот исправленная версия, которая работает на всех совместимых платформах:

#include <limits.h>

unsigned char reverse(unsigned char c) {
    int shift;
    unsigned char result = 0;

    for (shift = 0; shift < CHAR_BIT; shift++) {
        result <<= 1;
        result |= c & 1;
        c >>= 1;
    }
    return result;
}
0 голосов
/ 18 апреля 2010

0x01 означает 1 - единица в одном месте - и 0x80 означает 128 - 8 в шестидесятом месте. Эти числа относятся к младшему и старшему разрядам в восьмибитном числе соответственно. Сдвиг их дает маски для отдельных битов в байте.

Редактировать: В шестнадцатеричном числе цифры идут в шестнадцати степенях, а не в десяти. Таким образом, первая цифра справа - это единичное место (0x1 = 1), вторая цифра - это место шестидесяти (0x10 = 16), третья цифра - это место двести пятьдесят шесть (0x100 = 256), и и так далее.

...