Jak ustawić, wyczyścić i przełączyć pojedynczy bit?

Jak ustawić, wyczyścić i przełączyć bit W C / C++?

Author: WaleedYaser, 2008-09-07

26 answers

Ustawianie bitu

Użyj operatora bitowego OR (|), aby ustawić bit.

number |= 1UL << n;

To ustawi nTen bit number.

Użyj 1ULL, jeśli number jest szersza niż unsigned long; promocja 1UL << n następuje dopiero po ocenie 1UL << n, gdzie niezdefiniowanym zachowaniem jest przesunięcie o więcej niż szerokość long. To samo dotyczy wszystkich pozostałych przykładów.

Wyczyszczenie bitu

Użyj operatora bitowego i (&), aby wyczyścić trochę.

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

To wyczyści n Ten bit number. Musisz odwrócić łańcuch bitowy operatorem bitwise NOT (~), then I it.

Przełączanie bitów

Operator XOR (^) może być użyty do przełączania bitów.

number ^= 1UL << n;

To przełącza n Ten bit number.

Sprawdzanie bitu

Nie prosiłeś o to, ale równie dobrze mogę to dodać.

Aby sprawdzić bit, przesuń liczbę n w prawo, a następnie bitowo i it:

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

To umieści wartość n tego bitu number W Zmiennej bit.

Zmiana N TH bit na x

W przeciwieństwie do innych bitów w C++, bit ten nie może być używany w C++, ale może być używany w C++.]}
number ^= (-x ^ number) & (1UL << n);

Bit n zostanie ustawiony, jeśli x jest 1, i wyczyszczony, jeśli x jest 0. Jeśli x ma jakąś inną wartość, dostajesz śmieci. x = !!x spowoduje booleanizację do 0 lub 1.

Aby to uniezależnić od zachowania negacji dopełniacza 2 (gdzie -1 ma ustawione wszystkie bity, w przeciwieństwie do implementacji C++ dopełniacza 1 lub znaku/wielkości), użyj negacji niepodpisanej.

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

Lub

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

Ogólnie dobrym pomysłem jest używanie typów niepodpisanych do przenośnej manipulacji bitami.

Ogólnie dobrym pomysłem jest nie kopiowanie/wklejanie kodu w ogóle i tak wiele osób używa makr preprocesora (jak community wiki odpowiada dalej w dół ) lub jakiś rodzaj enkapsulacji.

 3077
Author: Jeremy Ruten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 18:42:18

Używanie standardowej biblioteki C++ : std::bitset<N>.

Lub wersjaBoost : boost::dynamic_bitset.

Nie ma potrzeby kręcić własnego:

#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
Wersja Boost pozwala na użycie zestawu bitów o rozmiarze runtime w porównaniu ze standardową biblioteką w czasie kompilacji.
 392
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 01:18:57

Inną opcją jest użycie pól bitowych:

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

struct bits mybits;

Definiuje 3-bitowe pole (właściwie to trzy 1-bitowe feldy). Operacje bitowe stają się teraz nieco (haha) prostsze:

Aby ustawić lub wyczyścić bit:

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

Aby przełączyć bit:

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

Sprawdzanie bitu:

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

To działa tylko z polami bitowymi o stałej wielkości. W przeciwnym razie musisz uciekać się do technik bit-twidling opisanych w poprzednich postach.

 216
Author: Ferruccio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-29 00:40:32

Używam makr zdefiniowanych w pliku nagłówkowym do obsługi Bit set I clear:

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

/* 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))
 127
Author: Steve Karg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 21:30:17

Czasem warto użyć enum do nazwy bitów:

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

Następnie używaj nazw później. Tzn. write

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

Aby ustawić, wyczyścić i przetestować. W ten sposób ukrywasz magiczne liczby przed resztą kodu.

Poza tym popieram rozwiązanie Jeremy ' ego.
 101
Author: dmckee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-18 15:54:21

Z 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)))
Dobrze, przeanalizujmy to...

Często spotykanym wyrażeniem, z którym masz problemy, jest "(1L

    0000 0000 0000 0000 0000 0000 0000 0001 binary.

Jeśli posn = = 8, to oceni

    0000 0000 0000 0000 0000 0001 0000 0000 binary.

W innych słowa, po prostu tworzy pole 0 ' S z 1 na określonym pozycji. Jedyną trudną częścią jest Makro BitClr (), w którym musimy ustawić pojedynczy bit 0 w polu 1 's. osiąga się to za pomocą 1' s dopełniacz tego samego wyrażenia oznaczonego operatorem tyldy ( ~ ).

Po utworzeniu maski zostanie zastosowana do argumentu tak, jak sugerujesz, za pomocą operatorów bitowych oraz (&), or ( | ) I xor ( ^ ). Od maski jest typu long, makra będą działać tak jak well on char 's, short' s, int ' s, lub Longa.

Najważniejsze jest to, że jest to ogólne rozwiązanie dla całej klasy problemy. Jest oczywiście możliwe, a nawet właściwe przepisanie odpowiednik dowolnego z tych makr z jawnymi wartościami maski za każdym razem, gdy potrzebuję, ale po co to robić? Pamiętaj, że podstawienie makro występuje w preprocesora i tak wygenerowany kod będzie odzwierciedlał fakt, że wartości są uważane za stałe przez kompilator - tzn. jest tak samo wydajne, aby użycie uogólnione makra, jak" odkrywać koło " za każdym razem, gdy trzeba zrobić trochę manipulacji.

Nieprzekonany? Oto kod testowy-użyłem Watcom C z pełną optymalizacją i bez użycia _cdecl, więc wynikający demontaż byłby tak czysty jak możliwe:

----[ 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 (zdemontowany) ]-----------------------------------------------

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

 35
Author: yogeesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 15:07:16

Dla początkujących chciałbym wyjaśnić nieco więcej na przykładzie:

Przykład:

value is 0x55;
bitnum : 3rd.

Użyty jest operator & Sprawdź 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)

Przełącz lub Przełącz:

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

| operator: Ustaw bit

0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)
 29
Author: kapilddit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-22 16:09:54

Użyj operatorów bitowych: & |

Aby ustawić ostatni bit w 000b:

foo = foo | 001b

Aby sprawdzić ostatni bit w foo:

if ( foo & 001b ) ....

Aby wyczyścić ostatni bit w foo:

foo = foo & 110b

Użyłem XXXb dla jasności. Prawdopodobnie będziesz pracować z reprezentacją szesnastkową, w zależności od struktury danych, w której pakujesz bity.

 28
Author: nsanders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 11:23:14

Oto moje ulubione bitowe makro arytmetyczne, które działa dla każdego typu unsigned integer array od unsigned char do size_t (który jest największym typem, który powinien być wydajny do pracy):

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

Aby ustawić bit:

BITOP(array, bit, |=);

Aby wyczyścić bit:

BITOP(array, bit, &=~);

Aby przełączyć bit:

BITOP(array, bit, ^=);

Aby przetestować bit:

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

Itd.

 24
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-09 14:21:00

Jak to jest oznaczone "embedded" zakładam, że używasz mikrokontrolera. Wszystkie powyższe sugestie są poprawne i działają ( read-modify-write, unions, structs, etc.).

Jednak podczas debugowania opartego na oscyloskopie byłem zdumiony odkryciem, że te metody mają znaczny narzut w cyklach CPU w porównaniu do zapisu wartości bezpośrednio do rejestrów PORTnSET / PORTnCLEAR micro, co robi prawdziwą różnicę tam, gdzie są ciasne pętle / przełączanie ISR o wysokiej częstotliwości Szpilki.

Dla tych nieznanych: w moim przykładzie mikro ma ogólny rejestr stanu pinów PORTn, który odzwierciedla piny wyjściowe, więc wykonanie PORTn / = BIT_TO_SET powoduje odczyt-modyfikację-zapis do tego rejestru. Jednak rejestry PORTnSET / PORTnCLEAR przyjmują "1", co oznacza" proszę uczynić ten bit 1 "(SET) lub" proszę uczynić ten bit zero "(CLEAR), a"0" oznacza "zostaw pin w spokoju". w związku z tym otrzymujesz dwa adresy portów w zależności od tego, czy ustawiasz lub czyścisz bit (nie zawsze wygodny), ale dużo szybsza reakcja i mniejszy zmontowany kod.

 22
Author: John U,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-14 15:23:17

Podejście bitfield ma inne zalety w wbudowanej arenie. Można zdefiniować strukturę, która mapuje bezpośrednio na bity w określonym rejestrze sprzętowym.

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;

Musisz być świadomy kolejności pakowania bitów - myślę, że najpierw jest to MSB, ale może to być zależne od implementacji. Sprawdź również, jak pola obsługi kompilatora przekraczają granice bajtów.

Można następnie odczytywać, zapisywać, testować poszczególne wartości jak wcześniej.

 21
Author: Roddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-06 11:30:16

Bardziej ogólne, dla dowolnych wielkości 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)))
 19
Author: bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 07:38:21

Sprawdzanie bitu w dowolnej lokalizacji w zmiennej dowolnego typu:

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

Przykładowe użycie:

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

Uwagi: Jest on zaprojektowany tak, aby był szybki (biorąc pod uwagę jego elastyczność) i nie rozgałęziający się. Skutkuje to wydajnym kodem maszynowym SPARC po skompilowaniu Sun Studio 8; testowałem go również przy użyciu MSVC++ 2008 na amd64. Możliwe jest tworzenie podobnych makr do ustawiania i usuwania bitów. Kluczową różnicą tego rozwiązania w porównaniu z wieloma innymi jest to, że działa dla dowolnej lokalizacji w prawie każdym typie zmiennej.

 17
Author: John Zwinck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-03 23:44:14

Jeśli robisz dużo trochę twidling może chcesz użyć masek, które sprawi, że całość szybciej. Poniższe funkcje są bardzo szybkie i wciąż elastyczne (pozwalają na przesuwanie bitów w Mapach bitowych o dowolnej wielkości).

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

Uwaga, Aby ustawić bit 'n' w 16-bitowej liczbie całkowitej, wykonaj następujące czynności:

TSetBit( n, &my_int);

Do ciebie należy upewnienie się, że numer bitu mieści się w zakresie mapy bitowej, którą przekazujesz. Zauważ, że dla małych procesorów endian, które bytes, words, dwords, qwords, itd., Mapuj poprawnie do siebie w pamięci (główny powód, dla którego małe procesory endian są "lepsze" niż procesory big-endian, Ah, czuję, że nadchodzi wojna płomieniowa...).

 13
Author: Tim Ring,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-05 11:20:35

Ten program ma zmienić dowolny bit danych z 0 Na 1 lub 1 na 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);
        }
    }
}
 12
Author: Gokul Naathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-22 16:07:42

Użyj tego:

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

    return num;
}
 11
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-22 16:06:03

Rozszerzanie na bitset ODPOWIEDŹ:

#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;
}
 9
Author: kendotwill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 04:33:41

Jeśli chcesz wykonać tę całą operację z programowaniem w C w jądrze Linuksa to proponuję użyć standardowych API jądra Linuksa.

Zobacz 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

Uwaga: tutaj cała operacja odbywa się w jednym kroku. Więc te wszystkie są gwarantowane atomic nawet na komputerach SMP i są przydatne aby zachować spójność między procesorami.

 9
Author: Jeegar Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-01 16:21:28

Visual C 2010, a być może wiele innych kompilatorów, posiada bezpośrednie wsparcie dla operacji bitowych wbudowanych. Co zaskakujące, to działa, nawet operator sizeof() działa poprawnie.

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

Więc, na twoje pytanie, IsGph [i] =1 lub IsGph [i] =0 sprawiają, że ustawianie i czyszczenie boolów jest łatwe.

Aby znaleźć znaki niedrukowalne...

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

Uwaga nie ma nic "specjalnego" w tym kodzie. Traktuje trochę jak liczbę całkowitą - która technicznie jest. 1-bitowa liczba całkowita, która może pomieścić 2 wartości i 2 tylko wartości.

Kiedyś użyłem tego podejścia, aby znaleźć zduplikowane rekordy pożyczek, gdzie loan_number był kluczem ISAM, używając 6-cyfrowego numeru pożyczki jako indeksu do tablicy bitów. Szybko i po 8 miesiącach okazało się, że system mainframe, z którego pobieraliśmy dane, faktycznie działał nieprawidłowo. Prostota macierzy bitowych sprawia, że zaufanie do ich poprawności jest bardzo wysokie - np. w stosunku do podejścia przeszukiwania.

 8
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-03 05:51:00

Użyj jednego z operatorów zdefiniowanych tutaj .

Aby ustawić bit, użyj int x = x | 0x?; gdzie ? jest pozycją bitową w postaci binarnej.

 5
Author: Jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-05 22:58:36

Oto kilka makr, których używam:

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)
 4
Author: sam msft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-06 23:11:18

Jak ustawić, wyczyścić i przełączyć pojedynczy bit?

Aby rozwiązać najczęstszą pułapkę kodowania podczas próby utworzenia maski:
1 nie zawsze jest wystarczająco szeroka

Jakie problemy zdarzają się, gdy number jest typu szerszego niż 1?
x może być zbyt duża dla zmiany 1 << x prowadzącej do niezdefiniowanego zachowania (UB). Nawet jeśli x nie jest zbyt wielka, ~ może nie odwrócić wystarczającej ilości najbardziej znaczących bitów.

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

Aby ubezpieczyć 1 jest wystarczająco szeroki:

Kod może używać 1ull lub pedantycznie (uintmax_t)1 i pozwolić kompilatorowi na optymalizację.

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

Lub cast-co sprawia, że problemy z kodowaniem/przeglądem / konserwacją utrzymują poprawny i aktualny cast.

number |= (type_of_number)1 << x;

Lub delikatnie wypromuj 1 wymuszając operację matematyczną, która jest co najmniej tak szeroka jak typ number.

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

Jak w przypadku większości manipulacji bitami, najlepiej pracować z typami unsigned zamiast signed ones

 3
Author: chux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 18:18:48
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);
}
 2
Author: Sazzad Hissain Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 12:35:12

A C++11 template version (put in a header):

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;}
}
 2
Author: Joakim L. Christiansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 20:51:05

Zmienna używana

int value, pos;

Wartość-Dane
pos-pozycja bitu, który chcemy ustawić, wyczyścić lub przełączyć
Ustaw bit

value = value | 1 << pos;

Wyczyść bit

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

Przełącz bit

value = value ^ 1 << pos;
 2
Author: Jeet Parikh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 17:32:56

Wypróbuj jedną z tych funkcji w języku C, aby zmienić N bit:

char bitfield;

// Start at 0th position

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

Lub

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

Lub

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;
}
 -1
Author: Vincet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 01:20:23