Двоичное число C в массиве в десятичное число

Что происходит внутри цикла в binary_array_to_numbers(). Я знаю, что он делает, но я не понимаю, как он это делает. Впервые вижу использование << и |. Заранее спасибо.

unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
   unsigned res = 0;
   for (size_t i = 0; i < count; i++)
      res = res << 1 | bits[i];
   return res;
}

int main(void) {
   unsigned bits[] = {0, 0, 1, 0};
   unsigned received = binary_array_to_numbers(bits, sizeof(bits) / sizeof(bits[0]));
   return 0;
}

Что вы имеете в виду под «десятичным»?

meaning-matters 11.05.2022 07:06
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
1
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Оператор сдвига влево res << 1 сдвигает разрешение на 1 бит, поэтому самый правый бит теперь равен нулю. Затем вы применяете побитовый оператор или |, чтобы установить этот самый правый бит в значение bits[i] (предполагается, что bits является массивом 0 или 1 и хранится с прямым порядком байтов, иначе ваш алгоритм не будет работать).

Скажем bits = { 1, 0, 1 } (т.е. 5; в вашем примере это интереснее, чем 2). Вот что происходит на каждой итерации:

0.

res = res << 1 | bits[0]
res = 0x0 << 1 | 1
res = 1
res = 1 << 1 | bits[1]
res = 0x2 | 0
res = 0x2
res = 0x2 << 1 | bits[2]
res = 0x4 | 1
res = 0x5

Оператор левой смены

Оператор сдвига влево сдвигает все биты влево на определенное количество заданных битов. Битовые позиции, освобожденные оператором сдвига влево, заполняются 0. Символом оператора сдвига влево является <<.

Побитовый оператор ИЛИ

Результат побитового ИЛИ равен 1, если хотя бы один соответствующий бит двух операндов равен 1. В C побитовый оператор ИЛИ обозначается |.

  • sizeof(bits) / sizeof(bits[0]) — это распространенный метод, когда вы хотите вычислить количество элементов массива фиксированного размера во время компиляции. В этом случае компилятор молча заменит все выражение на 4.

  • Результирующий целочисленный тип операции sizeof является типом size_t, который представляет собой большое целое число без знака, подходящее для описания размеров массивов и т. д. Поэтому этот тип используется в качестве параметра функции.

  • Массив передается функции как const unsigned *, что означает, что он доступен только для чтения и не будет изменен функцией. Это хорошая практика, и она называется константная корректность.

  • res в функции формирует бинарное битовое поле.

  • Приоритет оператора в выражении res = res << 1 | bits[i]; дает [] больше << больше | больше =. То есть это эквивалентно:

    res = ( (res << 1) | bits[i] );
    
  • res << 1 сдвигает предыдущий сохраненный результат на один бит влево. В первый раз цикла это все нули. Когда значение сдвигается, в младшем значащем бите (LSB) появляется ноль.

  • Побитовое ИЛИ | выполняется между всем, что хранится в res, тем, что хранится в bits[i], что в данном случае бывает либо 0, либо 1, хранящимся в младшем бите bits[i].

    Поскольку остальная часть bits[i] равна нулю, только эти данные LSB имеют значение для OR. А в случае res мы знаем, что его младший бит равен нулю. Таким образом, в этом конкретном случае это то же самое, что переместить содержимое bits[i] в младший бит res, не затрагивая другие биты, уже сохраненные в res.

  • Результатом будет двоичное битовое поле со значением 0010 или, если вы будете использовать шестнадцатеричное значение 0x2.

Другие вопросы по теме