Come si fa a impostare, eliminare e cambiare un singolo bit?
-
09-06-2019 - |
Domanda
Come si fa a impostare, chiaro, e passare un po ' in C/C++?
Soluzione
L'impostazione di un bit
Utilizzare l'operatore or bit a bit (|
) per impostare un po'.
number |= 1UL << n;
Che consente di impostare il n
th po ' di number
. n
dovrebbe essere pari a zero, se si desidera impostare il 1
st bit e così via fino a n-1
, se si desidera impostare il n
th po'.
Utilizzare 1ULL
se number
è più ampia rispetto a unsigned long
;promozione di 1UL << n
non accadrà fino a dopo la valutazione 1UL << n
dove è definito il comportamento di spostare di più rispetto alla larghezza di una long
.Lo stesso vale per tutti il resto degli esempi.
Rimozione di un po'
Utilizzare l'operatore and bit a bit (&
) per cancellare un po'.
number &= ~(1UL << n);
Che sarà chiaro il n
th po ' di number
.È necessario invertire la stringa di bit con bit a bit operatore NOT (~
), E poi farlo.
La commutazione di un po'
L'operatore XOR (^
) può essere utilizzato per cambiare un po'.
number ^= 1UL << n;
Che farà passare il n
th po ' di number
.
Controllando un po'
Non avete chiesto questo, ma potrei anche aggiungere.
Per controllare un po', sposta il numero n di destra, poi a livello di bit E:
bit = (number >> n) & 1U;
Mettere il valore della n
th po ' di number
nella variabile bit
.
Cambiando il nth po ' di x
Impostazione del n
th po ' per uno 1
o 0
può essere raggiunto con il seguente complemento a 2 implementazione di C++:
number ^= (-x ^ number) & (1UL << n);
Bit n
verrà impostato se x
è 1
, e se deselezionata x
è 0
.Se x
ha un altro valore, si ottiene spazzatura. x = !!x
sarà booleanize a 0 o 1.
Per fare questo indipendente di 2 complemento di negazione del comportamento (dove -1
ha tutti i bit impostati, a differenza di un complemento a 1 o segno/grandezza implementazione di C++), uso senza segno di negazione.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
o
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
E ' generalmente una buona idea di utilizzare i tipi senza segno per portatili di manipolazione dei bit.
o
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
sarà chiaro il n
th po ' e (x << n)
imposta il n
th po ' di x
.
E ' generalmente una buona idea di non copiare/incollare il codice in generale, e così molte persone usano macro del preprocessore (come la comunità wiki risposta più in basso) o un qualche tipo di incapsulamento.
Altri suggerimenti
Utilizzando la Libreria Standard di C++: std::bitset<N>
.
O il Boost versione: boost::dynamic_bitset
.
Non c'è bisogno di rotolare il vostro proprio:
#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
Il Boost versione permette l'esecuzione di dimensioni bitset rispetto a un la libreria standard in fase di compilazione di dimensioni bitset.
L'altra opzione è quella di utilizzare i campi di bit:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
definisce un 3-campo di bit (in realtà, è 1 po ' felds).Operazioni sui Bit, ora è diventata un po ' (ride) più semplice:
Per impostare o cancellare un po':
mybits.b = 1;
mybits.c = 0;
Per cambiare un po':
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
Controllando un po':
if (mybits.c) //if mybits.c is non zero the next line below will execute
Questo funziona solo con dimensioni fisse di campi di bit.Altrimenti devi ricorrere alla bit-giocherellando tecniche descritte nel post precedente.
Io uso le macro definite in un file di intestazione per gestire set di bit e chiaro:
/* 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 volte vale la pena enum
per nome i bit:
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
Quindi utilizzare il nomi in seguito.I. e.scrivere
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
per impostare, chiaro e test.In questo modo si nasconde la magia dei numeri dal resto del codice.
Diverso da quello che mi approva Jeremy soluzione.
Da snip-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)))
OK, vediamo di analizzare le cose...
L'espressione comune che ti sembra di avere problemi con in tutto "(1L << (pos))".Tutto questo non fa altro che creare una maschera con un singolo bit su e che funzionerà con qualsiasi tipo integer.Il "pos" argomento specifica il la posizione in cui si desidera che il bit.Se pos==0, quindi questa espressione valutare a:
0000 0000 0000 0000 0000 0000 0000 0001 binary.
Se pos==8, valuterà, a:
0000 0000 0000 0000 0000 0001 0000 0000 binary.
In altre parole, si crea semplicemente un campo di 0 con un 1 a specificato posizione.L'unica parte difficile è in BitClr() macro in cui abbiamo bisogno di impostare un singolo bit 0 in un campo di 1.Questo avviene tramite l'1 complemento della stessa espressione, come recita la tilde (~) per l'operatore.
Una volta che viene creata la maschera, a cui viene applicata l'argomento proprio come suggerisci tu, da utilizzare l'operatore and (&), or (|), xor (^) gli operatori.Dato che la maschera è di tipo long, la macro funziona altrettanto bene su char, short, int, o long.
La linea di fondo è che questa è una soluzione generale di un'intera classe di problemi.È possibile, naturalmente, e anche opportuno riscrivere la equivalente di una qualsiasi di queste macro con esplicita i valori della maschera ogni volta che si bisogno, ma perché farlo?Ricordate, la sostituzione di macro si verifica nel il preprocessore e così il codice generato in considerazione del fatto che i valori sono considerati costante dal compilatore - cioèè efficiente la generalizzata macro di "reinventare la ruota" ogni volta che avete bisogno di fare la manipolazione dei bit.
Non convinto?Ecco alcuni test di codice che ho usato Watcom C con l'ottimizzazione completa e senza l'utilizzo di _cdecl quindi il conseguente smontaggio sarebbe più pulito possibile:
----[ TEST.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 (smontato) ]-----------------------------------------------
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
----[ finis ]-----------------------------------------------------------------
Utilizzare gli operatori bit a bit: &
|
Per impostare ultimo bit in 000b
:
foo = foo | 001b
Per controllare l'ultimo bit foo
:
if ( foo & 001b ) ....
Per cancellare ultimo bit in foo
:
foo = foo & 110b
Ho usato XXXb
per maggiore chiarezza.Probabilmente lavorare con la rappresentazione ESADECIMALE, a seconda della struttura dati in cui sei imballaggio bit.
Per il principiante, vorrei spiegare un po ' di più con un esempio:
Esempio:
value is 0x55;
bitnum : 3rd.
Il &
operatore di controllare il 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)
Toggle o Flip:
0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)
|
operatore:impostare il bit
0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)
Ecco la mia preferita po ' di aritmetica macro, che funziona per qualsiasi tipo di unsigned integer array unsigned char
fino a size_t
(che è il tipo più grande che dovrebbe essere efficiente di lavorare con):
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
Per impostare un po':
BITOP(array, bit, |=);
Per cancellare un po':
BITOP(array, bit, &=~);
Per cambiare un po':
BITOP(array, bit, ^=);
Per testare un po':
if (BITOP(array, bit, &)) ...
ecc.
Il campo di bit approccio ha altri vantaggi incorporato arena.È possibile definire una struct che le mappe direttamente sul bit in un particolare registro hardware.
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;
È necessario essere consapevoli del bit ordine di imballaggio, penso sia MSB, ma questo può essere dipendente dall'implementazione.Inoltre, è possibile verificare come il compilatore gestori di campi attraversamento limiti di byte.
Quindi è possibile leggere, scrivere, testare i singoli valori come prima.
Questo è tagged "embedded" si assume che si sta utilizzando un microcontrollore.Tutti i suggerimenti sopra riportati sono validi & lavoro (read-modify-write, sindacati, strutture, etc.).
Tuttavia, durante un incontro con l'oscilloscopio a base di debug sono stato stupito di scoprire che questi metodi hanno un notevole sovraccarico in cicli di CPU rispetto alla scrittura di un valore direttamente al micro PORTnSET / PORTnCLEAR registri che fa veramente la differenza, dove ci sono loop / ad alta frequenza ISR commutazione pin.
Per chi non conoscesse:Nel mio esempio, il micro ha un generale pin-registro di stato PORTn che riflette il pin di uscita, in modo da fare PORTn |= BIT_TO_SET risultati in un read-modify-write per il registro.Tuttavia, il PORTnSET / PORTnCLEAR registri di prendere un '1' per dire "si prega di fare questo bit 1" (SET) o "si prega di prendere questo bit zero" (CHIARA) e un '0' significa "lasciare il pin da solo".così, si finisce con due indirizzi di porta a seconda se si sta selezionando o deselezionando la bit (non sempre facile), ma un molto di reazione più veloci e più piccoli assemblato.
Più in generale, per arbitrario di dimensioni bitmap:
#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)))
Controllare un po ' in una posizione arbitraria in una variabile di tipo arbitrario:
#define bit_test(x, y) ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )
Un esempio di utilizzo:
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;
}
Note: Questo è stato progettato per essere veloce (data la sua flessibilità) e non ramoso.Risultati efficiente SPARC codice macchina quando viene compilato Sun Studio 8;Ho testato anche utilizzando MSVC++ 2008 su amd64.È possibile fare un simile macro per impostare e cancellare bit.La differenza principale di questa soluzione rispetto a molti altri qui è che funziona per qualsiasi posizione in praticamente qualsiasi tipo di variabile.
Questo programma è quello di cambiare i dati di bit da 0 a 1 o da 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);
}
}
}
Se stai facendo un sacco di po ' con le mani in mano si potrebbe desiderare di utilizzare le maschere che rendono il tutto più veloce.Le seguenti funzioni sono molto veloci e sono ancora flessibili (consentono po ' con le mani in mano in mappe di bit di qualsiasi dimensione).
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;
}
Nota per impostare il bit 'n' in un numero intero a 16 bit si effettuano le seguenti operazioni:
TSetBit( n, &my_int);
Spetta a voi per assicurarsi che il numero di bit è all'interno della gamma della mappa di bit che si passa.Nota che per little endian processori di byte, parole, parole, qwords, ecc.... mappa correttamente a ogni altro in memoria (principale motivo che little endian processori sono migliori rispetto a big-endian processori, ah, mi sento una guerra fiamma venuta via...).
Uso questo:
int ToggleNthBit ( unsigned char n, int num )
{
if(num & (1 << n))
num &= ~(1 << n);
else
num |= (1 << n);
return num;
}
L'espansione di bitset
risposta:
#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 si desidera eseguire questo operazione con la programmazione C in Linux kernel quindi io suggerisco di usare le Api del kernel di Linux.
Vedere 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:Qui l'intera operazione avviene in un unico passaggio.Quindi, tutti questi sono garantiti per essere atomic anche su computer SMP e sono utili per mantenere la coerenza tra i processori.
Visual C 2010, e forse molti altri compilatori, avere il supporto diretto per le operazioni sui bit integrato.Sorprendentemente, questo funziona, anche il sizeof()
operatore funziona correttamente.
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);
}
Così, per la tua domanda, IsGph[i] =1
, o IsGph[i] =0
fare l'impostazione e cancellazione di bools facile.
Per trovare i caratteri non stampabili:
// 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;
}
}
Nota non c'è niente di "speciale" su questo codice.Si tratta un po ' come un numero intero che tecnicamente è.A 1 bit che può contenere 2 valori, e 2 valori.
Una volta ho usato questo approccio per trovare duplicati di prestito record, dove loan_number era l'ISAM chiave, utilizzando le 6 cifre del prestito numero come indice nella matrice di bit.Selvaggiamente veloce, e dopo 8 mesi, ha dimostrato che il sistema mainframe siamo riusciti ad ottenere i dati è in realtà funziona correttamente.La semplicità di matrici di bit rende la fiducia nella loro esattezza molto alta rispetto a un approccio alla ricerca, per esempio.
Utilizzare uno degli operatori come definito qui.
Per impostare un po', usato int x = x | 0x?;
dove ?
è la posizione del bit in forma binaria.
Qui ci sono alcune macro che 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)
Variabile utilizzata
int value, pos;
valore Dati
pos - posizione del bit che a noi interessano per impostare, eliminare o passare.
Impostare un po':
value = value | 1 << pos;
Chiaro un po':
value = value & ~(1 << pos);
Passare un po':
value = value ^ 1 << pos;
Come si fa a impostare, eliminare e cambiare un singolo bit?
Per affrontare una codifica comune insidia quando tenta di formare la maschera:
1
non è sempre abbastanza ampia
Quali sono i problemi accadere quando number
è una più ampia tipologia di 1
?
x
potrebbe essere troppo grande per il turno 1 << x
leader per un comportamento indefinito (UB).Anche se x
non è troppo grande, ~
non possono girare abbastanza più significativo-bit.
// 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
Per assicurare la 1 è abbastanza ampia:
Codice potrebbe utilizzare 1ull
o pedantemente (uintmax_t)1
e lasciare che il compilatore ottimizza.
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
O cast, il che rende per la codifica/revisione/manutenzione questioni talmente semplice mantenere aggiornati i cast corretto e aggiornato.
number |= (type_of_number)1 << x;
O delicatamente promuovere la 1
forzando un operazione matematica che è almeno altrettanto vasta come il tipo di number
.
number |= (number*0 + 1) << x;
Come con la maggior parte dei bit manipolazioni, meglio lavorare con unsigned tipi piuttosto che firmato quelli
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);
}
C++11 basati su modello versione (inserire una intestazione):
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;}
}
Provare una di queste funzioni in linguaggio C per cambiare n bit:
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;
}