Como é que se ajusta, se limpa e se troca um pouco?
Utilize o operador bitwise OR (|
) para definir um bit.
number |= 1UL << n;
Isso vai definir o "número". O n' deve ser zero, se você quiser definir o
1'st bit e assim por diante até o n-1', se você quiser definir o
n'th bit.
Utilize 1ULL' se o
número' for maior do que unsigned long'; a promoção de
1UL <<< n' só acontece depois de avaliar 1UL <<< n' onde é comportamento indefinido mudar por mais do que a largura de um
long'. O mesmo se aplica a todos os outros exemplos.
Utilize o bitwise AND operator (&
) para limpar um pouco.
number &= ~(1UL << n);
Isso vai limpar o "número". Você deve inverter a seqüência de bits com o operador bitwise NOT (~
), então AND it.
O operador XOR (^
) pode ser utilizado para alternar um pouco.
number ^= 1UL << n;
Isso vai alternar o "n" número.
Tu não pediste isto, mas mais vale acrescentar.
Para verificar um pouco, desloque o número n para a direita, depois um pouco para a direita E ele:
bit = (number >> n) & 1U;
Isso irá colocar o valor do n'th bit do
número' na variável `bit'.
A definição do n
th bit para 1
ou 0
pode ser alcançada com o seguinte em uma implementação do complemento C++ do 2:
number ^= (-x ^ number) & (1UL << n);
O bit n
será definido se x
for 1
, e limpo se x
for 0
. Se o x
tem algum outro valor, você recebe lixo. O x = !!x
vai booleanizá-lo para 0 ou 1.
Para tornar isto independente do comportamento de negação do complemento 2 (onde -1
tem todos os bits definidos, ao contrário de um complemento 1 ou implementação de sinal/magnitude C++), utilize negação não assinada.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
ou
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
Geralmente é uma boa idéia usar tipos não assinados para manipulação de bits portáteis.
ou
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL <<< n))
irá limpar o n
th bit e (x <<< n)
irá definir o n
th bit para x
.
Também é geralmente uma boa idéia não copiar/colar código em geral e muitas pessoas usam macros pré-processadoras (como a resposta da comunidade wiki mais abaixo) ou algum tipo de encapsulamento.
Às vezes vale a pena utilizar um enum
para nomear os bits:
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
Então use os nomes mais tarde. Isto é, escreva
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
para definir, limpar e testar. Assim você esconde os números mágicos do resto do seu código.
Tirando isso, eu apoio a solução do Jeremy.
Use os operadores bitwise: &
|
Para definir o último bit em 000b
:
foo = foo | 001b
Para verificar o último bit em foo
:
if ( foo & 001b ) ....
Para limpar o último pedaço em "pés":
foo = foo & 110b
Eu usei XXXb
para maior clareza. Você provavelmente estará trabalhando com representação HEX, dependendo da estrutura de dados na qual você está empacotando bits.