Pergunta

Como você define, limpa e alterna um pouco em C/C++?

Foi útil?

Solução

Definindo um pouco

Use o operador OR bit a bit (|) para definir um pouco.

number |= 1UL << n;

Isso definirá o no pedaço de number. n deve ser zero, se você quiser definir o 1st bit e assim por diante até n-1, se você quiser definir o na parte.

Usar 1ULL se number é mais largo que unsigned long;Promoção de 1UL << n não acontece até depois de avaliar 1UL << n onde é um comportamento indefinido mudar mais do que a largura de um long.O mesmo se aplica a todos os demais exemplos.

Limpando um pouco

Use o operador AND bit a bit (&) para limpar um pouco.

number &= ~(1UL << n);

Isso limpará o no pedaço de number.Você deve inverter a sequência de bits com o operador NOT bit a bit (~), então E isso.

Alternando um pouco

O operador XOR (^) pode ser usado para alternar um pouco.

number ^= 1UL << n;

Isso irá alternar o no pedaço de number.

Verificando um pouco

Você não pediu isso, mas posso muito bem acrescentar.

Para verificar um bit, desloque o número n para a direita e, em seguida, AND bit a bit:

bit = (number >> n) & 1U;

Isso colocará o valor do no pedaço de number na variável bit.

Alterando a no pouco para x

Configurando o no bit para qualquer um 1 ou 0 pode ser alcançado com o seguinte em uma implementação C++ de complemento de 2:

number ^= (-x ^ number) & (1UL << n);

Pedaço n será definido se x é 1, e limpo se x é 0.Se x tem algum outro valor, você obtém lixo. x = !!x irá booleanizá-lo para 0 ou 1.

Para tornar isso independente do comportamento de negação do complemento de 2 (onde -1 tem todos os bits definidos, ao contrário de complemento de 1 ou implementação de sinal/magnitude C++), use negação sem sinal.

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 ideia usar tipos não assinados para manipulação portátil de bits.

ou

number = (number & ~(1UL << n)) | (x << n);

(number & ~(1UL << n)) irá limpar o no bit e (x << n) definirá o no pouco para x.

Geralmente também é uma boa ideia não copiar/colar código em geral e muitas pessoas usam macros de pré-processador (como a resposta do wiki da comunidade mais abaixo) ou algum tipo de encapsulamento.

Outras dicas

Usando a biblioteca C++ padrão: std::bitset<N>.

Ou o Impulsionar versão: boost::dynamic_bitset.

Não há necessidade de criar o seu próprio:

#include <bitset>
#include <iostream>

int main()
{
    std::bitset<5> x;

    x[1] = 1;
    x[2] = 0;
    // Note x[0-4]  valid

    std::cout << x << std::endl;
}

[Alpha:] > ./a.out
00010

A versão Boost permite um bitset de tamanho de tempo de execução comparado com um biblioteca padrão bitset de tamanho de tempo de compilação.

A outra opção é usar campos de bits:

struct bits {
    unsigned int a:1;
    unsigned int b:1;
    unsigned int c:1;
};

struct bits mybits;

define um campo de 3 bits (na verdade, são três campos de 1 bit).As operações de bits agora se tornam um pouco (haha) mais simples:

Para definir ou limpar um pouco:

mybits.b = 1;
mybits.c = 0;

Para alternar um pouco:

mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1;  /* all work */

Verificando um pouco:

if (mybits.c)  //if mybits.c is non zero the next line below will execute

Isso funciona apenas com campos de bits de tamanho fixo.Caso contrário, você terá que recorrer às técnicas de manipulação de bits descritas nos posts anteriores.

Eu uso macros definidas em um arquivo de cabeçalho para lidar com a definição e limpeza de bits:

/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b))))        // '!!' to make sure this returns 0 or 1

/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK_ALL(x,y) (((x) & (y)) == (y))   // warning: evaluates y twice
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))

Às vezes vale a pena usar um enum para nome os pedaços:

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}

Então use o nomes mais tarde.Ou sejaescrever

thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}

para definir, limpar e testar.Dessa forma, você oculta os números mágicos do restante do seu código.

Fora isso, endosso a solução de Jeremy.

De recorte-c.zipé bitops.h:

/*
**  Bit set, clear, and test operations
**
**  public domain snippet by Bob Stout
*/

typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

OK, vamos analisar as coisas...

A expressão comum com a qual você parece estar tendo problemas em tudo isso é "(1L << (posn))".Tudo isso é criar uma máscara com um único bit e que funcionará com qualquer tipo inteiro.O argumento "Posn" especifica a posição em que você deseja o bit.Se Posn == 0, então esta expressão será avaliada para:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

Se posn==8, será avaliado como:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

Em outras palavras, ele simplesmente cria um campo de 0 com 1 na posição especificada.A única parte complicada é na macro bitclr (), onde precisamos definir um único bits em um campo de 1.Isso é realizado usando o complemento do 1 da mesma expressão indicada pelo operador TILDE (~).

Depois que a máscara é criada, é aplicada ao argumento da mesma forma que você sugere, pelo uso dos operadores bit e (&), ou (|) e xor (^).Como a máscara é do tipo longa, as macros também funcionarão bem em Char, Short's, Int's ou Long.

O ponto principal é que esta é uma solução geral para uma classe inteira de problemas.É claro que é possível e até apropriado reescrever o equivalente a qualquer uma dessas macros com valores explícitos de máscara toda vez que você precisar de um, mas por que fazê -lo?Lembre -se, a substituição da macro ocorre no pré -processador e, portanto, o código gerado refletirá o fato de que os valores são considerados constantes pelo compilador - ou seja,É tão eficiente usar as macros generalizadas que "reinventar a roda" toda vez que você precisar fazer manipulação de bits.

Não convencido?Aqui está algum código de teste - usei o Watcom C com otimização total e sem usar _cdecl para que a desmontagem resultante seria o mais limpa possível:

----[TESTE.C]----------------------------------------- -----------------------

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

int bitmanip(int word)
{
      word = BitSet(word, 2);
      word = BitSet(word, 7);
      word = BitClr(word, 3);
      word = BitFlp(word, 9);
      return word;
}

----[TESTE.OUT (desmontado)]-------------------------------------- ---------

Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS

Segment: _TEXT  BYTE   00000008 bytes  
 0000  0c 84             bitmanip_       or      al,84H    ; set bits 2 and 7
 0002  80 f4 02                          xor     ah,02H    ; flip bit 9 of EAX (bit 1 of AH)
 0005  24 f7                             and     al,0f7H
 0007  c3                                ret     

No disassembly errors

----[final]------------------------------------------- ----------------------

Use os operadores bit a bit: & |

Para definir o último bit 000b:

foo = foo | 001b

Para verificar a última parte foo:

if ( foo & 001b ) ....

Para limpar a última parte foo:

foo = foo & 110b

eu usei XXXb para maior clareza.Você provavelmente trabalhará com representação HEX, dependendo da estrutura de dados na qual está empacotando os bits.

Para o iniciante gostaria de explicar um pouco mais com um exemplo:

Exemplo:

value is 0x55;
bitnum : 3rd.

O & operador é usado, verifique o bit:

0101 0101
&
0000 1000
___________
0000 0000 (mean 0: False). It will work fine if the third bit is 1 (then the answer will be True)

Alternar ou inverter:

0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)

| operador:definir o bit

0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)

Aqui está minha macro aritmética de bits favorita, que funciona para qualquer tipo de array inteiro não assinado de unsigned char até size_t (que é o maior tipo com o qual deve ser eficiente trabalhar):

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))

Para definir um pouco:

BITOP(array, bit, |=);

Para esclarecer um pouco:

BITOP(array, bit, &=~);

Para alternar um pouco:

BITOP(array, bit, ^=);

Para testar um pouco:

if (BITOP(array, bit, &)) ...

etc.

A abordagem bitfield tem outras vantagens na área embarcada.Você pode definir uma estrutura que mapeie diretamente os bits em um registro de hardware específico.

struct HwRegister {
    unsigned int errorFlag:1;  // one-bit flag field
    unsigned int Mode:3;       // three-bit mode field
    unsigned int StatusCode:4;  // four-bit status code
};

struct HwRegister CR3342_AReg;

Você precisa estar ciente da ordem de empacotamento de bits - acho que primeiro é o MSB, mas isso pode depender da implementação.Além disso, verifique como o seu compilador manipula os campos que cruzam os limites de bytes.

Você pode então ler, escrever e testar os valores individuais como antes.

Como está marcado como "incorporado", presumo que você esteja usando um microcontrolador.Todas as sugestões acima são válidas e funcionam (leitura-modificação-gravação, uniões, estruturas, etc.).

No entanto, durante uma sessão de depuração baseada em osciloscópio, fiquei surpreso ao descobrir que esses métodos têm uma sobrecarga considerável nos ciclos da CPU em comparação com a gravação de um valor diretamente nos registros PORTnSET/PORTnCLEAR do micro, o que faz uma diferença real onde há loops estreitos/altos. -pinos de alternância do ISR de frequência.

Para quem não conhece:No meu exemplo, o micro possui um registro geral de estado de pino PORTn que reflete os pinos de saída, portanto, fazer PORTn |= BIT_TO_SET resulta em uma leitura-modificação-gravação nesse registro.No entanto, os registradores PORTnSET / PORTnCLEAR assumem um '1' para significar "por favor, torne este bit 1" (SET) ou "por favor, torne este bit zero" (CLEAR) e um '0' para significar "deixe o pino em paz".então, você acaba com dois endereços de porta dependendo se você está configurando ou limpando o bit (nem sempre conveniente), mas um muito reação mais rápida e código montado menor.

Mais geral, para bitmaps de tamanho arbitrário:

#define BITS 8
#define BIT_SET(  p, n) (p[(n)/BITS] |=  (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] &   (0x80>>((n)%BITS)))

Verifique um bit em um local arbitrário em uma variável de tipo arbitrário:

#define bit_test(x, y)  ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )

Uso de amostra:

int main(void)
{
    unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

    for (int ix = 0; ix < 64; ++ix)
        printf("bit %d is %d\n", ix, bit_test(arr, ix));

    return 0;
}

Notas:Ele foi projetado para ser rápido (dada a sua flexibilidade) e sem ramificações.Isso resulta em código de máquina SPARC eficiente quando compilado no Sun Studio 8;Também testei usando MSVC++ 2008 em AMD64.É possível fazer macros semelhantes para configurar e limpar bits.A principal diferença desta solução em comparação com muitas outras aqui é que ela funciona para qualquer local e praticamente qualquer tipo de variável.

Este programa serve para alterar qualquer bit de dados de 0 para 1 ou de 1 para 0:

{
    unsigned int data = 0x000000F0;
    int bitpos = 4;
    int bitvalue = 1;
    unsigned int bit = data;
    bit = (bit>>bitpos)&0x00000001;
    int invbitvalue = 0x00000001&(~bitvalue);
    printf("%x\n",bit);

    if (bitvalue == 0)
    {
        if (bit == 0)
            printf("%x\n", data);
        else
        {
             data = (data^(invbitvalue<<bitpos));
             printf("%x\n", data);
        }
    }
    else
    {
        if (bit == 1)
            printf("elseif %x\n", data);
        else
        {
            data = (data|(bitvalue<<bitpos));
            printf("else %x\n", data);
        }
    }
}

Se você estiver mexendo muito, talvez queira usar máscaras que tornarão tudo mais rápido.As funções a seguir são muito rápidas e ainda flexíveis (permitem mexer em mapas de bits de qualquer tamanho).

const unsigned char TQuickByteMask[8] =
{
   0x01, 0x02, 0x04, 0x08,
   0x10, 0x20, 0x40, 0x80,
};


/** Set bit in any sized bit mask.
 *
 * @return    none
 *
 * @param     bit    - Bit number.
 * @param     bitmap - Pointer to bitmap.
 */
void TSetBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] |= TQuickByteMask[n];        // Set bit.
}


/** Reset bit in any sized mask.
 *
 * @return  None
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
void TResetBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] &= (~TQuickByteMask[n]);    // Reset bit.
}


/** Toggle bit in any sized bit mask.
 *
 * @return   none
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
void TToggleBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] ^= TQuickByteMask[n];        // Toggle bit.
}


/** Checks specified bit.
 *
 * @return  1 if bit set else 0.
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
short TIsBitSet( short bit, const unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;    // Index to byte.
    n = bit % 8;    // Specific bit in byte.

    // Test bit (logigal AND).
    if (bitmap[x] & TQuickByteMask[n])
        return 1;

    return 0;
}


/** Checks specified bit.
 *
 * @return  1 if bit reset else 0.
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
short TIsBitReset( short bit, const unsigned char *bitmap)
{
    return TIsBitSet(bit, bitmap) ^ 1;
}


/** Count number of bits set in a bitmap.
 *
 * @return   Number of bits set.
 *
 * @param    bitmap - Pointer to bitmap.
 * @param    size   - Bitmap size (in bits).
 *
 * @note    Not very efficient in terms of execution speed. If you are doing
 *        some computationally intense stuff you may need a more complex
 *        implementation which would be faster (especially for big bitmaps).
 *        See (http://graphics.stanford.edu/~seander/bithacks.html).
 */
int TCountBits( const unsigned char *bitmap, int size)
{
    int i, count = 0;

    for (i=0; i<size; i++)
        if (TIsBitSet(i, bitmap))
            count++;

    return count;
}

Observe que para definir o bit 'n' em um número inteiro de 16 bits, faça o seguinte:

TSetBit( n, &my_int);

Cabe a você garantir que o número do bit esteja dentro do intervalo do mapa de bits que você passa.Observe que, para processadores little endian, bytes, palavras, dwords, qwords, etc. são mapeados corretamente entre si na memória (principal razão pela qual os processadores little endian são 'melhores' do que os processadores big-endian, ah, sinto uma guerra violenta chegando sobre...).

Usa isto:

int ToggleNthBit ( unsigned char n, int num )
{
    if(num & (1 << n))
        num &= ~(1 << n);
    else
        num |= (1 << n);

    return num;
}

Expandindo no bitset responder:

#include <iostream>
#include <bitset>
#include <string>

using namespace std;
int main() {
  bitset<8> byte(std::string("10010011");

  // Set Bit
  byte.set(3); // 10010111

  // Clear Bit
  byte.reset(2); // 10010101

  // Toggle Bit
  byte.flip(7); // 00010101

  cout << byte << endl;

  return 0;
}

Se você quiser realizar toda esta operação com programação C no Kernel Linux então sugiro usar APIs padrão do kernel Linux.

Ver https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html

set_bit  Atomically set a bit in memory
clear_bit  Clears a bit in memory
change_bit  Toggle a bit in memory
test_and_set_bit  Set a bit and return its old value
test_and_clear_bit  Clear a bit and return its old value
test_and_change_bit  Change a bit and return its old value
test_bit  Determine whether a bit is set

Observação:Aqui toda a operação acontece em uma única etapa.Então, tudo isso tem a garantia de ser atômico Mesmo em computadores SMP e são úteis para manter a coerência entre os processadores.

O Visual C 2010, e talvez muitos outros compiladores, possuem suporte direto integrado para operações de bits.Surpreendentemente, isso funciona, mesmo o sizeof() operador funciona corretamente.

bool    IsGph[256], IsNotGph[256];

//  Initialize boolean array to detect printable characters
for(i=0; i<sizeof(IsGph); i++)  {
    IsGph[i] = isgraph((unsigned char)i);
}

Então, para sua pergunta, IsGph[i] =1, ou IsGph[i] =0 facilita a configuração e a limpeza de bools.

Para encontrar caracteres não imprimíveis:

//  Initialize boolean array to detect UN-printable characters, 
//  then call function to toggle required bits true, while initializing a 2nd
//  boolean array as the complement of the 1st.
for(i=0; i<sizeof(IsGph); i++)  {
    if(IsGph[i])    {
         IsNotGph[i] = 0;
    }   else   {
         IsNotGph[i] = 1;
    }
}

Observe que não há nada de "especial" neste código.Ele trata um pouco como um número inteiro - o que tecnicamente é.Um número inteiro de 1 bit que pode conter 2 valores e apenas 2 valores.

Certa vez, usei essa abordagem para encontrar registros de empréstimo duplicados, onde número_do_empréstimo era a chave ISAM, usando o número do empréstimo de 6 dígitos como um índice na matriz de bits.Extremamente rápido, e depois de 8 meses, provou que o sistema mainframe do qual recebíamos os dados estava de fato com defeito.A simplicidade das matrizes de bits aumenta muito a confiança em sua correção - em comparação com uma abordagem de pesquisa, por exemplo.

Use um dos operadores conforme definido aqui.

Para definir um pouco, usado int x = x | 0x?; onde ? é a posição do bit na forma binária.

Aqui estão algumas macros que uso:

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)

Variável usada

int value, pos;

valor - Dados
pos - posição do bit que estamos interessados ​​em definir, limpar ou alternar.

Defina um pouco:

value = value | 1 << pos;

Esclareça um pouco:

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

Alterne um pouco:

value = value ^ 1 << pos;

Como você define, limpa e alterna um único bit?

Para resolver uma armadilha comum de codificação ao tentar formar a máscara:
1 nem sempre é largo o suficiente

Que problemas acontecem quando number é um tipo mais amplo do que 1?
x pode ser grande demais para a mudança 1 << x levando a comportamento indefinido (UB).Ainda que x não é muito bom, ~ pode não inverter os bits mais significativos o suficiente.

// 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

Para garantir que 1 seja largo o suficiente:

Código poderia usar 1ull ou pedantemente (uintmax_t)1 e deixe o compilador otimizar.

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

Ou elenco - o que cria problemas de codificação/revisão/manutenção, mantendo o elenco correto e atualizado.

number |= (type_of_number)1 << x;

Ou promova suavemente o 1 forçando uma operação matemática que seja pelo menos tão ampla quanto o tipo de number.

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

Tal como acontece com a maioria das manipulações de bits, é melhor trabalhar com não assinado tipos em vez de assinado uns

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);
}

Uma versão modelada em C++ 11 (colocada em um cabeçalho):

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;}
}

Experimente uma destas funções na linguagem C para alterar n bits:

char bitfield;

// Start at 0th position

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

Ou

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

Ou

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top