Jump to content

    
Sign in to follow this  
ViKo

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

Recommended Posts

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

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

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

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

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

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

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

 

Reg |= N * MASK_0;

 

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

 

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

...

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this