Jump to content

    

Как с помощью #define определить позицию бита

Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8.

В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего.

Как это сделать макрофункцией?

Тогда я смогу задавать сдвиг "магических чисел" в регистре по имени группы битов в этом регистре.

P.S. Обратная функция легко делается сдвигом 1 << NUM.

Share this post


Link to post
Share on other sites

Для одного бита: log2(0x0100)=8

Не скажу за все препроцессоры, но AVRASM2 понимает такое LOG2(0x0100)

Share this post


Link to post
Share on other sites
Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8.

В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего.

Как это сделать макрофункцией?

Что-то в голову ничего, кроме вариаций на тему условного rvalue, не приходит.

P.S. Обратная функция легко делается сдвигом 1 << NUM.

Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально.

Share this post


Link to post
Share on other sites
Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально.

Шутки шутите?

 

Э, да ведь можно с помощью #if перебрать все варианты!

#if   (VAL == 0x8000)
#define NUM 15
#elif (VAL == 0x4000)
#define NUM 14
...

 

А еще проще через лестницу тернарных операторов. :yeah:

Share this post


Link to post
Share on other sites
А еще проще через лестницу тернарных операторов. :yeah:

о, а это хорошая идея.

Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции

//calc position of rightmost nonzero bit
#define m2b(x) (\
(((x & -x) & 0x0000FFFF) ? 0 : 16)+\
(((x & -x) & 0x00FF00FF) ? 0 : 8)+\
(((x & -x) & 0x0F0F0F0F) ? 0 : 4)+\
(((x & -x) & 0x33333333) ? 0 : 2)+\
(((x & -x) & 0x55555555) ? 0 : 1)+\
((x & -x) ? 0 : 1))

Плюс в том, что это макроопределение можно использовать прямо внутри выражения.

Share this post


Link to post
Share on other sites

Правильно ли я понял: допустим у вас есть

#define MASK 0x000FF0

И вы хотите из этого MASK получить 4 чтобы сделать Reg = N << 4;

 

Можно сделать (я делаю) так:

Reg = N * (MASK & -MASK);

Share this post


Link to post
Share on other sites
Правильно ли я понял:...

Да, правильно. Спасибо! Супер.

И ведь видел когда-то... :rolleyes:

Share this post


Link to post
Share on other sites

Если описать конкретно младший бит в группе, то можно пользоваться тем же умножением, что я и сам делаю ( :lol: показывал в другой теме). Только сомножители местами переставлены. :rolleyes:

 

Reg |= N * MASK_0;

 

Компилятор все эти умножения на сдвиги заменяет, естественно.

 

Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции

...

Плюс в том, что это макроопределение можно использовать прямо внутри выражения.

Да, спасибо, макро работает, компилируется в число.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this