Пользовательская обратная функция 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