Как установить, очистить и переключить один бит?
Чтобы устранить распространенную ошибку кодирования при попытке сформировать маску:
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;
Как и в большинстве битовых манипуляций, лучше всего работать с беззнаковыми типами, а не со знаком с