реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как с помощью #define определить позицию бита
ViKo
сообщение Aug 28 2014, 12:38
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8.
В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего.
Как это сделать макрофункцией?
Тогда я смогу задавать сдвиг "магических чисел" в регистре по имени группы битов в этом регистре.
P.S. Обратная функция легко делается сдвигом 1 << NUM.
Go to the top of the page
 
+Quote Post
ae_
сообщение Aug 28 2014, 13:36
Сообщение #2


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Для одного бита: log2(0x0100)=8
Не скажу за все препроцессоры, но AVRASM2 понимает такое LOG2(0x0100)
Go to the top of the page
 
+Quote Post
gosha-z
сообщение Aug 28 2014, 13:45
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 327
Регистрация: 30-10-05
Пользователь №: 10 288



Цитата(ViKo @ Aug 28 2014, 16:38) *
Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8.
В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего.
Как это сделать макрофункцией?

Что-то в голову ничего, кроме вариаций на тему условного rvalue, не приходит.
Цитата(ViKo @ Aug 28 2014, 16:38) *
P.S. Обратная функция легко делается сдвигом 1 << NUM.

Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально.
Go to the top of the page
 
+Quote Post
msalov
сообщение Aug 28 2014, 13:52
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Для этих целей есть Find First Set (ffs).

Или вот ещё -> "Number of leading zeros algorithms"
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2014, 14:12
Сообщение #5


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(gosha-z @ Aug 28 2014, 16:45) *
Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально.

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

Э, да ведь можно с помощью #if перебрать все варианты!
Код
#if   (VAL == 0x8000)
#define NUM 15
#elif (VAL == 0x4000)
#define NUM 14
...


А еще проще через лестницу тернарных операторов. yeah.gif
Go to the top of the page
 
+Quote Post
SSerge
сообщение Aug 28 2014, 15:14
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(ViKo @ Aug 28 2014, 21:12) *
А еще проще через лестницу тернарных операторов. yeah.gif

о, а это хорошая идея.
Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции
Код
//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))

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


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 28 2014, 20:26
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Правильно ли я понял: допустим у вас есть
Код
#define MASK 0x000FF0
И вы хотите из этого MASK получить 4 чтобы сделать Reg = N << 4;

Можно сделать (я делаю) так:
Код
Reg = N * (MASK & -MASK);


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2014, 21:10
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Aug 28 2014, 23:26) *
Правильно ли я понял:...

Да, правильно. Спасибо! Супер.
И ведь видел когда-то... rolleyes.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 29 2014, 10:04
Сообщение #9


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



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

Код
Reg |= N * MASK_0;


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

Цитата(SSerge @ Aug 28 2014, 18:14) *
Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции
...
Плюс в том, что это макроопределение можно использовать прямо внутри выражения.

Да, спасибо, макро работает, компилируется в число.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 00:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.0142 секунд с 7
ELECTRONIX ©2004-2016