Как вы устанавливаете, очищаете и переключаете один бит? - PullRequest
2337 голосов
/ 07 сентября 2008

Как установить, очистить и немного переключить в C / C ++?

Ответы [ 26 ]

5 голосов
/ 11 июля 2018

Используемая переменная

int value, pos;

значение - данные
pos - позиция бита, который нам нужно установить, очистить или переключить
Установить бит

value = value | 1 << pos;

Очистить немного

value = value & ~(1 << pos); 

Переключить немного

value = value ^ 1 << pos;
5 голосов
/ 07 февраля 2015

Вот некоторые макросы, которые я использую:

SET_FLAG(Status, Flag)            ((Status) |= (Flag))
CLEAR_FLAG(Status, Flag)          ((Status) &= ~(Flag))
INVALID_FLAGS(ulFlags, ulAllowed) ((ulFlags) & ~(ulAllowed))
TEST_FLAGS(t,ulMask, ulBit)       (((t)&(ulMask)) == (ulBit))
IS_FLAG_SET(t,ulMask)             TEST_FLAGS(t,ulMask,ulMask)
IS_FLAG_CLEAR(t,ulMask)           TEST_FLAGS(t,ulMask,0)
4 голосов
/ 21 февраля 2018
int set_nth_bit(int num, int n){

    return (num | 1 << n);
}

int clear_nth_bit(int num, int n){

    return (num & ~( 1 << n));
}

int toggle_nth_bit(int num, int n){

    return num ^ (1 << n);
}

int check_nth_bit(int num, int n){

    return num & (1 << n);
}
4 голосов
/ 27 сентября 2017

Как установить, очистить и переключить один бит?

Чтобы устранить распространенную ошибку кодирования при попытке сформировать маску:
1 не всегда достаточно широк

Какие проблемы возникают, когда number более широкий тип, чем 1?
x может быть слишком велико для сдвига 1 << x, ведущего к неопределенному поведению (UB). Даже если x не слишком велико, ~ может не отражать достаточно старших значащих бит.

// assume 32 bit int/unsigned
unsigned long long number = foo();

unsigned x = 40; 
number |= (1 << x);  // UB
number ^= (1 << x);  // UB
number &= ~(1 << x); // UB

x = 10;
number &= ~(1 << x); // Wrong mask, not wide enough

Чтобы обеспечить 1 достаточно широко:

Код может использовать 1ull или педантично (uintmax_t)1 и позволить оптимизировать компилятор.

number |= (1ull << x);
number |= ((uintmax_t)1 << x);

Или приведение - что устраняет проблемы с кодированием / проверкой / обслуживанием, поддерживая приведение правильного и актуального.

number |= (type_of_number)1 << x;

Или осторожно продвигать 1, форсируя математическую операцию, которая по ширине меньше, чем тип number.

number |= (number*0 + 1) << x;

Как и в большинстве битовых манипуляций, лучше всего работать с беззнаковыми типами, а не со знаком с

3 голосов
/ 10 февраля 2018

Шаблонная версия C ++ 11 (помещается в заголовок):

namespace bit {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bit) {variable |=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bit) {variable ^=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline bool test (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);}
}

namespace bitmask {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bits) {variable |= bits;}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bits) {variable &= ~bits;}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bits) {variable ^= bits;}
    template <typename T1, typename T2> inline bool test_all(T1 &variable, T2 bits) {return ((variable & bits) == bits);}
    template <typename T1, typename T2> inline bool test_any(T1 &variable, T2 bits) {return variable & bits;}
}
0 голосов
/ 27 мая 2014

Попробуйте изменить одну из следующих функций на языке C: n 1001 *

char bitfield;

// Start at 0th position

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}

Или

void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}

Или

void chang_n_bit(int n, int value)
{
    if(value)
        bitfield |= 1 << n;
    else
        bitfield &= ~0 ^ (1 << n);
}

char get_n_bit(int n)
{
    return (bitfield & (1 << n)) ? 1 : 0;
}
...