C / C ++ проверяет, установлен ли один бит, то есть переменная int - PullRequest
91 голосов
/ 07 февраля 2009
int temp = 0x5E; // in binary 0b1011110.

Есть ли такой способ проверить, равен ли бит 3 в темпе 1 или 0 без смещения и маскирования битов.

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

Ответы [ 18 ]

145 голосов
/ 07 февраля 2009

В C, если вы хотите скрыть битовую манипуляцию, вы можете написать макрос:

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

и используйте его для проверки n th бита с правого конца:

CHECK_BIT(temp, n - 1)

В C ++ вы можете использовать std :: bitset .

77 голосов
/ 07 февраля 2009

Проверьте, установлен ли бит N (начиная с 0):

temp & (1 << N)

Для этого нет встроенной функции.

21 голосов
/ 07 февраля 2009

Я бы просто использовал std :: bitset, если это C ++. Просто. Прямодушная. Нет шансов на глупые ошибки.

typedef std::bitset<sizeof(int)> IntBits;
bool is_set = IntBits(value).test(position);

или как насчет этой глупости

template<unsigned int Exp>
struct pow_2 {
    static const unsigned int value = 2 * pow_2<Exp-1>::value;
};

template<>
struct pow_2<0> {
    static const unsigned int value = 1;
};

template<unsigned int Pos>
bool is_bit_set(unsigned int value)
{
    return (value & pow_2<Pos>::value) != 0;
} 

bool result = is_bit_set<2>(value);
11 голосов
/ 07 февраля 2009

Согласно этому описанию битовых полей , существует метод определения и доступа к полям напрямую. Пример в этой записи:

struct preferences {
    unsigned int likes_ice_cream : 1;
    unsigned int plays_golf : 1;
    unsigned int watches_tv : 1;
    unsigned int reads_books : 1;
}; 

struct preferences fred;

fred.likes_ice_cream = 1;
fred.plays_golf = 1;
fred.watches_tv = 1;
fred.reads_books = 0;

if (fred.likes_ice_cream == 1)
    /* ... */

Также там есть предупреждение:

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

11 голосов
/ 07 февраля 2009

Да, я знаю, что "не имеет" , чтобы сделать это таким образом. Но я обычно пишу:

    /* Return type (8/16/32/64 int size) is specified by argument size. */
template<class TYPE> inline TYPE BIT(const TYPE & x)
{ return TYPE(1) << x; }

template<class TYPE> inline bool IsBitSet(const TYPE & x, const TYPE & y)
{ return 0 != (x & y); }

например:.

IsBitSet( foo, BIT(3) | BIT(6) );  // Checks if Bit 3 OR 6 is set.

Среди прочего, этот подход:

  • Вмещает 8/16/32/64 битовых целых.
  • Обнаруживает вызовы IsBitSet (int32, int64) без моего ведома и согласия.
  • Встроенный шаблон, поэтому нет необходимости вызывать функцию.
  • const & ссылок, поэтому ничего не нужно для дублирования / копирования. И мы гарантируем, что компилятор подберет любые опечатки, которые пытаются изменить аргументы.
  • 0! = делает код более понятным и понятным. Основным моментом при написании кода всегда является четкое и эффективное общение с другими программистами, в том числе с менее квалифицированными.
  • Хотя это и не применимо к этому конкретному случаю ... В общем случае шаблонные функции избегают проблемы оценки аргументов несколько раз. Известная проблема с некоторыми макросами #define.
    Например: # определить ABS (X) (((X) <0)? - (X): (X)) <br>ABS (i ++);
10 голосов
/ 06 августа 2015

То, что выбранный ответ делает на самом деле неправильно. Приведенная ниже функция вернет битовую позицию или 0 в зависимости от того, активирован ли бит на самом деле. Это не то, о чем просил плакат.

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

Вот то, что изначально искал плакат. Приведенная ниже функция вернет 1 или 0, если бит активирован, а не позиция.

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
6 голосов
/ 07 февраля 2009

Вы можете использовать Bitset - http://www.cppreference.com/wiki/stl/bitset/start.

5 голосов
/ 07 февраля 2009

Использовать std :: bitset

#include <bitset>
#include <iostream>

int main()
{
    int temp = 0x5E;
    std::bitset<sizeof(int)*CHAR_BITS>   bits(temp);

    // 0 -> bit 1
    // 2 -> bit 3
    std::cout << bits[2] << std::endl;
}
4 голосов
/ 09 апреля 2018

Я использую это:

#define CHECK_BIT(var,pos) ( (((var) & (pos)) > 0 ) ? (1) : (0) )

, где "pos" определяется как 2 ^ n (например, 1,2,4,8,16,32 ...)

Возвращает: 1 если правда 0, если ложь

4 голосов
/ 07 февраля 2009

Существует, а именно, _bittest внутренняя инструкция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...