Pregunta

¿Cómo se configura, borra y alterna un poco en C/C++?

¿Fue útil?

Solución

poniendo un poco

Utilice el operador OR bit a bit (|) para configurar un poco.

number |= 1UL << n;

Eso establecerá el nel poco de number. n debe ser cero, si desea configurar el 1st bit y así sucesivamente hasta n-1, si desea configurar el ndécimo bit.

Usar 1ULL si number es más ancho que unsigned long;Promoción de 1UL << n no sucede hasta después de evaluar 1UL << n donde es un comportamiento indefinido cambiar más que el ancho de un long.Lo mismo se aplica al resto de los ejemplos.

aclarando un poco

Utilice el operador AND bit a bit (&) para aclarar un poco.

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

Eso limpiará el nel poco de number.Debe invertir la cadena de bits con el operador NOT bit a bit (~), luego Y eso.

alternando un poco

El operador XOR (^) se puede utilizar para alternar un poco.

number ^= 1UL << n;

Eso alternará el nel poco de number.

comprobando un poco

No pediste esto, pero también podría agregarlo.

Para verificar un poco, mueva el número n hacia la derecha, luego bit a bit Y:

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

Eso pondrá el valor de la nel poco de number en la variable bit.

Cambiando el norteel bit a X

Configurando el nel bit a cualquiera 1 o 0 se puede lograr con lo siguiente en una implementación de C++ en complemento a 2:

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

Poco n se establecerá si x es 1, y borrado si x es 0.Si x tiene algún otro valor, obtienes basura. x = !!x lo booleanizará a 0 o 1.

Para hacer esto independiente del comportamiento de negación en complemento a 2 (donde -1 tiene todos los bits configurados, a diferencia de una implementación de C++ en complemento a 1 o de signo/magnitud), use negación sin signo.

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

o

unsigned long newbit = !!x;    // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);

Generalmente es una buena idea utilizar tipos sin firmar para la manipulación de bits portátiles.

o

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

(number & ~(1UL << n)) limpiará el nel poco y (x << n) establecerá el nel bit a x.

En general, también es una buena idea no copiar/pegar código en general y mucha gente usa macros de preprocesador (como la respuesta wiki de la comunidad más abajo) o algún tipo de encapsulación.

Otros consejos

Usando la biblioteca estándar de C++: std::bitset<N>.

O el Aumentar versión: boost::dynamic_bitset.

No es necesario que hagas el tuyo propio:

#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

La versión Boost permite un conjunto de bits del tamaño de tiempo de ejecución en comparación con un biblioteca estándar Conjunto de bits de tamaño de tiempo de compilación.

La otra opción es utilizar campos de bits:

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

struct bits mybits;

define un campo de 3 bits (en realidad, son tres campos de 1 bit).Las operaciones de bits ahora se vuelven un poco (jaja) más simples:

Para configurar o borrar un poco:

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

Para alternar un poco:

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

Comprobando un poco:

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

Esto sólo funciona con campos de bits de tamaño fijo.De lo contrario, tendrás que recurrir a las técnicas de manipulación de bits descritas en publicaciones anteriores.

Utilizo macros definidas en un archivo de encabezado para manejar la configuración y el borrado 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))

A veces vale la pena utilizar un enum a nombre los bits:

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

Luego usa el nombres mas tarde.Es decir.escribir

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

para configurar, borrar y probar.De esta manera ocultas los números mágicos del resto de tu código.

Aparte de eso, apoyo la solución de Jeremy.

De recorte-c.zip's 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)))

Bueno, analicemos las cosas...

La expresión común con la que parece tener problemas en todos estos es "(1L << (posn))".Todo esto hace es crear una máscara con un solo bit y que funcionará con cualquier tipo entero.El argumento "POSN" especifica la posición en la que desea el bit.Si posn == 0, esta expresión evaluará a:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

Si posn==8, se evaluará como:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

En otras palabras, simplemente crea un campo de 0 con un 1 en la posición especificada.La única parte difícil es en la macro bitclr () donde necesitamos establecer un solo 0 bits en un campo de 1.Esto se logra utilizando el complemento de 1 de la misma expresión que se denota por el operador Tilde (~).

Una vez que se crea la máscara, se aplica al argumento tal como sugiere, mediante el uso de los operadores bitwise y (&), o (|) y Xor (^).Dado que la máscara es de tipo larga, las macros funcionarán igual de bien en Char's, Short's, Int's o Long's.

La conclusión es que esta es una solución general para una clase completa de problemas.Es, por supuesto, posible e incluso apropiado reescribir el equivalente de cualquiera de estas macros con valores de máscara explícitos cada vez que necesita uno, pero ¿por qué hacerlo?Recuerde, la sustitución macro ocurre en el preprocesador y, por lo tanto, el código generado reflejará el hecho de que los valores son considerados constantes por el compilador, es decir,Es tan eficiente usar las macros generalizadas como para "reinventar la rueda" cada vez que necesite hacer una manipulación de bits.

¿No estás convencido?Aquí hay algún código de prueba: utilicé Watcom C con optimización completa y sin usar _CDECL, por lo que el desmontaje resultante sería lo más limpio posible:

----[ PRUEBA.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;
}

----[ TEST.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

----[ fin ]------------------------------------------- ----------------------

Utilice los operadores bit a bit: & |

Para configurar el último bit 000b:

foo = foo | 001b

Para comprobar el último bit foo:

if ( foo & 001b ) ....

Para borrar el último bit en foo:

foo = foo & 110b

solía XXXb para mayor claridad.Probablemente trabajará con representación HEX, dependiendo de la estructura de datos en la que esté empaquetando los bits.

Para los principiantes me gustaría explicar un poco más con un ejemplo:

Ejemplo:

value is 0x55;
bitnum : 3rd.

El & Se utiliza el operador. Verifique el 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 o voltear:

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

| operador:establecer el bit

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

Aquí está mi macro aritmética de bits favorita, que funciona para cualquier tipo de matriz de enteros sin signo de unsigned char hasta size_t (que es el tipo más grande con el que debería ser eficiente trabajar):

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

Para configurar un poco:

BITOP(array, bit, |=);

Para aclarar un poco:

BITOP(array, bit, &=~);

Para alternar un poco:

BITOP(array, bit, ^=);

Para probar un poco:

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

etc.

El enfoque de campo de bits tiene otras ventajas en el ámbito integrado.Puede definir una estructura que se asigne directamente a los bits en un registro de hardware particular.

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;

Debe tener en cuenta el orden de empaquetado de los bits; creo que es MSB primero, pero esto puede depender de la implementación.Además, verifique cómo su compilador maneja los campos que cruzan los límites de bytes.

Luego podrá leer, escribir y probar los valores individuales como antes.

Como esto está etiquetado como "integrado", asumiré que estás usando un microcontrolador.Todas las sugerencias anteriores son válidas y funcionan (lectura-modificación-escritura, uniones, estructuras, etc.).

Sin embargo, durante una sesión de depuración basada en osciloscopio, me sorprendió descubrir que estos métodos tienen una sobrecarga considerable en los ciclos de la CPU en comparación con escribir un valor directamente en los registros PORTnSET/PORTnCLEAR del micro, lo que marca una diferencia real donde hay bucles estrechos/altos. -Pasadores de conmutación de frecuencia ISR.

Para aquellos que no están familiarizados:En mi ejemplo, el micro tiene un registro general de estado de pin PORTn que refleja los pines de salida, por lo que al hacer PORTn |= BIT_TO_SET se produce una lectura, modificación y escritura en ese registro.Sin embargo, los registros PORTnSET / PORTnCLEAR toman un '1' para significar "haga este bit en 1" (SET) o "haga este bit en cero" (CLEAR) y un '0' para significa "deje el pin en paz".por lo tanto, terminará con dos direcciones de puerto dependiendo de si está configurando o borrando el bit (no siempre es conveniente), pero una mucho reacción más rápida y código ensamblado más pequeño.

Más general, para mapas de bits de tamaño arbitrario:

#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 un bit en una ubicación arbitraria en una variable de tipo arbitrario:

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

Uso de muestra:

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:Está diseñado para ser rápido (dada su flexibilidad) y no ramificado.Da como resultado un código de máquina SPARC eficiente cuando se compila Sun Studio 8;También lo probé usando MSVC++ 2008 en amd64.Es posible crear macros similares para configurar y borrar bits.La diferencia clave de esta solución en comparación con muchas otras aquí es que funciona para cualquier ubicación en prácticamente cualquier tipo de variable.

Este programa sirve para cambiar cualquier bit de datos de 0 a 1 o de 1 a 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);
        }
    }
}

Si estás jugando mucho, es posible que quieras usar máscaras que harán que todo sea más rápido.Las siguientes funciones son muy rápidas y aún flexibles (permiten jugar con bits en mapas de bits de cualquier tamaño).

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

Tenga en cuenta que para configurar el bit 'n' en un entero de 16 bits, haga lo siguiente:

TSetBit( n, &my_int);

Depende de usted asegurarse de que el número de bits esté dentro del rango del mapa de bits que pasa.Tenga en cuenta que para los procesadores little endian los bytes, palabras, dwords, qwords, etc., se asignan correctamente entre sí en la memoria (la razón principal por la que los procesadores little endian son "mejores" que los procesadores big-endian, ah, siento que se avecina una guerra de llamas en...).

Utilizar esta:

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

    return num;
}

Ampliando el bitset respuesta:

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

Si desea realizar toda esta operación con programación C en el núcleo de linux entonces sugiero utilizar las API estándar del kernel de 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

Nota:Aquí toda la operación ocurre en un solo paso.Así que se garantiza que todos estos serán atómico Incluso en las computadoras SMP y son útiles para mantener la coherencia en los procesadores.

Visual C 2010, y quizás muchos otros compiladores, tienen soporte directo integrado para operaciones de bits.Sorprendentemente, esto funciona, incluso el sizeof() El operador funciona correctamente.

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

Entonces, a tu pregunta, IsGph[i] =1, o IsGph[i] =0 facilita la configuración y eliminación de bools.

Para buscar caracteres no imprimibles:

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

Tenga en cuenta que este código no tiene nada de "especial".Se trata un poco como un número entero, que técnicamente lo es.Un entero de 1 bit que puede contener 2 valores y solo 2 valores.

Una vez utilicé este enfoque para encontrar registros de préstamos duplicados, donde número_préstamo era la clave ISAM, usando el número de préstamo de 6 dígitos como índice en la matriz de bits.Salvajemente rápido, y después de 8 meses, se demostró que el sistema mainframe del que estábamos obteniendo los datos en realidad no funcionaba correctamente.La simplicidad de las matrices de bits hace que la confianza en su exactitud sea muy alta, frente a un enfoque de búsqueda, por ejemplo.

Utilice uno de los operadores tal como se define aquí.

Para fijar un poco, se utiliza int x = x | 0x?; dónde ? es la posición del bit en forma binaria.

Aquí hay algunas 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)

Variable utilizada

int value, pos;

datos de valor
pos - posición del bit que nos interesa configurar, borrar o alternar.

Establecer un poco:

value = value | 1 << pos;

Aclarar un poco:

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

Alternar un poco:

value = value ^ 1 << pos;

¿Cómo se configura, borra y alterna un solo bit?

Para abordar un error de codificación común al intentar formar la máscara:
1 no siempre es lo suficientemente ancho

¿Qué problemas ocurren cuando number es un tipo más amplio que 1?
x puede ser demasiado bueno para el turno 1 << x llevando a comportamiento indefinido (UB).Incluso si x no es demasiado bueno, ~ Es posible que no se volteen suficientes bits más significativos.

// 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 asegurar que 1 sea lo suficientemente ancho:

El código podría usar 1ull o pedantemente (uintmax_t)1 y dejar que el compilador optimice.

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

O transmitir, lo que genera problemas de codificación/revisión/mantenimiento para mantener la transmisión correcta y actualizada.

number |= (type_of_number)1 << x;

O promover suavemente el 1 forzando una operación matemática que sea al menos tan amplia como el tipo de number.

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

Como ocurre con la mayoría de las manipulaciones de bits, es mejor trabajar con no firmado tipos en lugar de firmado unos

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

Una versión con plantilla de C++ 11 (colocada en un encabezado):

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

Pruebe una de estas funciones en lenguaje C para cambiar n bits:

char bitfield;

// Start at 0th position

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

O

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

O

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top