Заполнение переменным количеством единиц

#c #bit-manipulation #bitwise-operators

#c #битовая манипуляция #побитовые операторы

Вопрос:

Каков наилучший способ заполнить переменную неизвестным (во время компиляции) количеством единиц? Например, скажем:

 int n = 5;
int b = fillwithones(5);
 

теперь b содержит 11111 (в двоичном формате).

Я не могу просто жестко закодировать int b = 31, потому что n заранее неизвестно (в моем приложении).

Я мог бы сделать что-то вроде этого:

 int b = pow(2, n) - 1
 

Но использование pow кажется очень расточительным.

Спасибо!

Ответ №1:

Вы можете использовать сдвиг влево, а затем вычесть 1:

 unsigned int b = (1U << n) - 1U;

// Broken down into steps
//  1           = 00000001b
//  1 << 5      = 00100000b
// (1 << 5) - 1 = 00011111b
 

Причина, по которой это работает, заключается в том, что 1 сдвиг влево n раз совпадает с 2 n, поскольку каждая единственная позиция бита представляет степень 2.

Комментарии:

1. Лучше всего использовать unsigned вместо int этого.

2. @TomZych: был в процессе этого исправления, вы быстры, сэр 😉

3.Я бы выбрал unsigned long long (-1ULL >> (sizeof (unsigned long long) - n) , но постоянное сворачивание в любом случае даст тот же результат.

4. n я думаю, @Alex здесь не является постоянным; Кстати, умножьте sizeof на 8 ( CHAR_BIT )

Ответ №2:

Забавный способ получить старшие биты равными 1, а младшие биты равными нулю — использовать этот приятный трюк:

 #include <limits.h>

...

int b = INT_MIN >> n;
 

Это работает, потому что операция сдвига влево для отрицательного числа сохранит знак операции, а поскольку INT_MIN равно 10000 ….0000, сдвиг его на n влево даст вам n бит до 1, но с другой стороны.