Обнаружение, установлен ли бит (во время компиляции)

Как определить, установлен ли бит в позиции n в постоянной переменной?


person There is nothing we can do    schedule 15.04.2011    source источник
comment
Переменная не существует во время компиляции, верно?   -  person Petar Minchev    schedule 15.04.2011
comment
В переменной? Во время компиляции? Можете ли вы привести пример?   -  person Johnsyweb    schedule 15.04.2011
comment
Вы не можете - переменная изменяется во время выполнения. Возможно, вы имеете в виду константу?   -  person Erik    schedule 15.04.2011
comment
@Извините, ребята, имелось в виду постоянное.   -  person There is nothing we can do    schedule 15.04.2011
comment
@Там: ты прав, они все неправы. В C++, когда мы делаем const int n = 21;, n действительно называется переменной, даже если она не может изменяться (3/4: переменная вводится объявлением объекта). Тот факт, что терминология C++ не совсем соответствует английскому языку, — это то, к чему должны привыкнуть программисты на C++, потому что, если они этого не сделают, они в конечном итоге неправильно интерпретируют то или иное в стандарте, например, думая, что то, что сказано о переменных, не соответствует действительности. не применяется к n, потому что это (по их мнению, но не по стандарту) константа, а не переменная.   -  person Steve Jessop    schedule 15.04.2011


Ответы (3)


template<std::uint64_t N, std::uint8_t Bit>
struct is_bit_set
{
    static bool const value = !!(N & 1u << Bit);
};

!! используется для краткого преобразования значения в bool и предотвращения предупреждений компилятора об усечении данных.

person ildjarn    schedule 15.04.2011
comment
этот ответ самый приятный на мой взгляд. - person There is nothing we can do; 15.04.2011

int const a = 4;
int const bitset = !!((1 << 2) & a);

Теперь bitset это 1. Было бы 0, если бы вы, например, сохранили 3. Да, a — это переменная.

person Johannes Schaub - litb    schedule 15.04.2011
comment
Почему бы не просто int bitset = ((1 << 2) & a) != 0);? - person sharptooth; 15.04.2011
comment
@RedX да bitset - это постоянное выражение. Вы можете использовать его для измерений массива, таких как int array[bitset + 1];. - person Johannes Schaub - litb; 15.04.2011
comment
@Johannes, спасибо за ответ, не могли бы вы объяснить, почему это работает? - person There is nothing we can do; 15.04.2011
comment
@johannes Хорошо. Другой вопрос: зачем вам двойное отрицание в начале? - person RedX; 15.04.2011
comment
@RedX: первый приводит к bool (только значение 0 или 1); второй дает действительно желаемое значение. - person ildjarn; 15.04.2011
comment
@RedX, потому что иначе bitset содержит 4, а не 1. @Там, en.wikipedia.org/wiki/Bitwise_operation, поиск И и битовые сдвиги. - person Johannes Schaub - litb; 15.04.2011
comment
@Johannes +1, так как это хороший ответ, но я соглашусь с Ильдьярном, так как он больше похож на C++. - person There is nothing we can do; 15.04.2011
comment
@Johnsyweb, только если у вас есть воображение;) - person There is nothing we can do; 15.04.2011
comment
Кроме того, мой ответ приведет к неопределенному поведению, если вы сдвинете его таким образом, что число станет отрицательным. Это справедливый выбор, так как он явно больше думал над своим ответом. - person Johannes Schaub - litb; 15.04.2011
comment
@Johannes Я рад, что ты согласен со мной в этом. - person There is nothing we can do; 15.04.2011

То же самое, что предлагает пользователь ildjarn в его ответ, но с так называемым "инструмент с перечислением", который гарантирует, что компилятор выполнит все вычисления во время компиляции:

template<std::uint64_t N, std::uint8_t Bit>
struct is_bit_set
{
    enum { value = ( N & (1u << Bit) ) != 0 };
};
person sharptooth    schedule 15.04.2011
comment
Я не думаю, что это необходимо для любого компилятора, совместимого с C++03/C++11, но в данный момент я слишком устал, чтобы копаться в стандарте. В любом случае вам, вероятно, следует изменить его на !!(N & (1u << Bit)), чтобы значение было строго ограничено 0 или 1. - person ildjarn; 15.04.2011
comment
@ildjarn: Спасибо, я отредактировал его аналогичным образом. - person sharptooth; 15.04.2011