Пользовательская обратная функция uint16_t возвращает 0x8000

    uint16_t ReverseInt16(uint16_t nonreversed) {
    uint16_t reversed = 0;
    reversed |= (nonreversed & 1 << 15) << 0; //check if bit 15 of nonreversed int is 1, if yes, write 1 to position 0, else write 0 to position 0
    reversed |= (nonreversed & 1 << 14) << 1;
    reversed |= (nonreversed & 1 << 13) << 2;
    reversed |= (nonreversed & 1 << 12) << 3;
    reversed |= (nonreversed & 1 << 11) << 4;
    reversed |= (nonreversed & 1 << 10) << 5;
    reversed |= (nonreversed & 1 << 9) << 6;
    reversed |= (nonreversed & 1 << 8) << 7;
    reversed |= (nonreversed & 1 << 7) << 8;
    reversed |= (nonreversed & 1 << 6) << 9;
    reversed |= (nonreversed & 1 << 5) << 10;
    reversed |= (nonreversed & 1 << 4) << 11;
    reversed |= (nonreversed & 1 << 3) << 12;
    reversed |= (nonreversed & 1 << 2) << 13;
    reversed |= (nonreversed & 1 << 1) << 14;
    reversed |= (nonreversed & 1 << 0) << 15;
    return reversed;
}

Мне нужно перевернуть бит uint16_t, поэтому я написал эту функцию, которая читает по битам исходный uint_t и записывает их в другую uint, но в обратной битовой позиции. Проблема в том, что когда я передаю целое число больше 0x00 (0), функция возвращает максимальное значение uint16_t.

Я новичок в битовых операциях c.

Спасибо за ответы.

РЕДАКТИРОВАТЬ: "Лучший алгоритм для обращения бит (от MSB->LSB до LSB->MSB) в C" использует 32-битные целые!

3 ответа

Решение

Я думаю, что вы имеете в виду следующее:)

#include <stdio.h>
#include <stdint.h>

uint16_t ReverseInt16( uint16_t nonreversed ) 
{
    uint16_t reversed = 0;

    for ( uint16_t i = 0; i < 16; i++ )
    {
        reversed |= ( nonreversed >> ( 16 - i - 1 ) & 1 ) << i;
    }        

    return reversed;
}

int main( void )
{
    uint16_t x = 0x1234;

    printf( "%x\n", x );
    printf( "%x\n", ReverseInt16( x ) );

}    

Выход программы

1234
2c48

Что касается вашего кода, то он не меняет биты. Например, рассмотрим заявление

reversed |= (nonreversed & 1 << 15) << 0;

1 << 15 дает в шестнадцатеричной записи 8000

тогда, например, если MSB установлен, то (nonreversed & 1 << 15) дает также 8000, Вам нужно сдвинуть результат вправо

reversed |= (nonreversed & 1 << 15) >> 15;

но вы пытаетесь сдвинуть его влево

reversed |= (nonreversed & 1 << 15) << 0;

Я вижу две проблемы (приоритет оператора и неправильные сдвиги), давайте рассмотрим пример того, что вы делаете для первого бита:

reversed |= (nonreversed & 1 << 15) << 0;

Приоритет оператора вводит в заблуждение и имеет более высокий приоритет, чем <<, тогда он должен быть:

reversed |= (nonreversed & (1 << 15)) << 0;

Теперь давайте посмотрим, что он делает, представьте, что нереверсным является 100000000000000b,

тогда (не обращенный & (1 << 15)) равен 100000000000000b & 100000000000000b,

это дает 100000000000000b

Если вы сдвинете его на 0, то он останется 100000000000000b (тогда 15-й бит не будет перемещен в позицию 0), поэтому, если вы хотите инвертировать битовую строку, вам нужно сказать:

reversed |= (nonreversed & (1 << 15)) >> 15;

То же самое относится и к другим битам (позаботьтесь о приоритете оператора и переместите бит в нужное место). Разборчивость может быть улучшена с помощью петли. Вот как я бы это реализовал:

uint16_t ReverseInt16(uint16_t nonreversed) {
  uint16_t reversed = 0;
  for(uint16_t bit=0; bit<16; ++bit) {
     reversed |= (uint16_t)((nonreversed & (1 << bit) != 0)) << (15 - bit);
  }
  return reversed;
}

Выражение nonreversed & (1 << bit)!= 0 является логическим значением, при преобразовании в uint16_t оно означает 0, если false, и 1, если true. 1 - бит в нулевой позиции, который я сдвигаю в нужном месте (<< (15 - бит)).

Чтобы дополнить некоторую информацию о приоритете оператора C,

  • побитовое & имеет более низкий приоритет, чем <<
    Итак, выражение nonreversed & 1 << 15 эквивалентно nonreversed & (1 << 15), Однако рекомендуется использовать круглые скобки, чтобы обеспечить приоритет.

  • Вот типичное использование, которое требует скобки
    if ((a & mask) == flag) // внутренние скобки обязательны, но их легко забыть

  • Таблица приоритетов оператора C

Приоритет оператора C

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