Kaip nustatyti, išvalyti ir perjungti vieną bitą?

Kaip nustatyti, išvalyti ir perjungti bitus C / C + +?

2210
07 сент. nustatė JeffV 07 sept. 2008-09-07 03:42 '08 at 3:42 2008-09-07 03:42
@ 27 atsakymai

Nustatyti bitai

Naudokite bitų OR operatorių ( | ), kad nustatytumėte bitą.

 number |= 1UL << n; 

Tai nustatys n bitą. n turi būti lygus nuliui, jei norite nustatyti 1 bitą ir pan. n-1 jei norite nustatyti n bitą.

Naudokite 1ULL jei number didesnis nei unsigned long ; skatinimas 1UL << n įvyksta tik po vertinimo 1UL << n kai neapibrėžtas elgesys pasikeičia ilgiau nei plotis. Tas pats pasakytina ir apie visus kitus pavyzdžius.

Valymo bitai

Naudokite bitų ir operatorių ( > ), kad pašalintumėte bitą.

 number  ~(1UL << n); 

Taip bus išvalytas number n . Turite invertuoti bitų eilutę su bitų NOT ( ~ ) operatoriumi, tada AND.

Pakeiskite šiek tiek

XOR operatorius ( ^ ) gali būti naudojamas bitams perjungti.

 number ^= 1UL << n; 

Tai perjungs skaičių n .

Patikrinkite bitą

Jūs to neprašėte, bet taip pat galėčiau ją pridėti.

Jei norite patikrinti šiek tiek, perkelkite skaičių n dešinėje, tada bitiau.

 bit = (number >> n)  1U; 

Tokiu būdu number n bitų reikšmė bus n į bit kintamąjį.

Pakeiskite nd bitą į x

n bitų nustatymą į 1 arba 0 galima pasiekti naudojant šiuos du „C ++“ papildymus:

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

n bitas bus nustatytas, jei x yra 1 , ir išvalytas, jei x yra 0 . Jei x turi skirtingą reikšmę, gausite šiukšlių. x = !!x būna jį 0 arba 1.

Kad jis būtų nepriklausomas nuo papildomų 2 priedų elgesio (kur -1 turi visus nustatytus bitus, o ne 1 papildinio arba C + + ženklo / vertės įgyvendinimą), naudokite nepasirašytą neigimą.

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

arba

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

Paprastai gera idėja naudoti nešifruotus tipus nešiojamiems bitų manipuliacijoms.

Apskritai, taip pat yra gera idėja ne kopijuoti / įklijuoti kodo kaip visumos, todėl daugelis žmonių naudoja išankstinio apdorojimo makrokomandas (pvz., Atsakymą iš bendruomenės wiki toliau ) arba tam tikrą kapsulę.

3179
07 сент. Atsakymas, kurį pateikė Jeremy Ruten 07 Sep 2008-09-07 03:50 '08 at 3:50 am 2008-09-07 03:50

Naudojant standartinę C ++ biblioteką: std::bitset<N> .

Arba padidinti : boost::dynamic_bitset .

Nereikia apsisukti:

 #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 

„Boost“ versija leidžia nustatyti bitų ir bitų dydį, palyginti su standartiniu bitų sparta.

405
18 сент. Martin York atsakymas rugsėjo 18 d 2008-09-18 03:34 '08 at 3:34 nuo 2008-09-18 03:34

Kita galimybė yra naudoti bitų laukus:

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

apibrėžia 3 bitų lauką (iš tikrųjų tai yra trys vieno bitų laukai). Dabar bitų operacijos tampa vis paprastesnės (haha):

Jei norite nustatyti arba išvalyti šiek tiek:

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

Norėdami perjungti bitą:

 mybits.a = !mybits.a; mybits.b = ~mybits.b; mybits.c ^= 1;  

Patikrinkite bitą:

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

Tai veikia tik su fiksuoto dydžio bitais. Priešingu atveju turėsite pasinaudoti ankstesniais pranešimais aprašytais bitų sukimo metodais.

224
11 сент. Atsakymą pateikė „ Ferruccio 11 sep“. 2008-09-11 03:56 '08 at 3:56 nuo 2008-09-11 03:56

Naudoju antraštės faile apibrėžtas makrokomandas, kad galėčiau apdoroti bitą ir išvalyti:

  #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  #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)) 
138
05 нояб. Atsakymą pateikė Steve Karg 05 lapkričio. 2008-11-05 01:35 '08 at 1:35 am 2008-11-05 01:35

Kartais verta naudoti „ enum žymėti bitus:

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

Tada vėliau naudokite pavadinimus. Tai yra parašyti

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

įdiegti, išvalyti ir patikrinti. Tokiu būdu jūs paslėpsite stebuklingus numerius iš likusio kodo.

Be to, pritariu Jeremy sprendimui.

106
09 сент. atsakymas ddckee 09 Sep. 2008-09-09 00:07 '08 0:07 2008-09-09 00:07

Nuo snip-c.zip bitops.h:

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

Na, leiskite jam analizuoti dalykus ...

Bendra išraiška, su kuria susiduriate visais šiais atvejais, yra „(1L << (posn))“. Visa tai sukuria kaukę su vienu bitu ir jis veiks su bet kuriuo sveikojo skaičiaus tipu. „Posn“ argumentas rodo poziciją, kurioje norite bitų. Jei yra == 0, ši išraiška bus vertinama kaip:

  0000 0000 0000 0000 0000 0000 0000 0001 binary. 

Jei bus = 8, jis įvertins

  0000 0000 0000 0000 0000 0001 0000 0000 binary. 

Kitaip tariant, jis tiesiog sukuria lauką 0 su 1 nurodytoje padėtyje. Vienintelė sudėtinga dalis yra BitClr () makrokomandoje, kur 1 lauke reikia nustatyti vieną bitą 0 bitą. Tai pasiekiama pridedant vieną prie tos pačios išraiškos, kurią žymi „tilde“ operatorius (~).

Kai tik sukuriama kaukė, jis taikomas argumentui tokiu pat būdu, kaip manote, naudodami bitų ir ( arba (|) ir xor (^) operatorius. Kadangi kaukė yra ilgo tipo, makrokomandos veiks taip pat, kaip ir char, short, int arba long.

Esmė yra ta, kad tai yra bendras sprendimas visai problemų grupei. Žinoma, įmanoma ir netgi patartina perrašyti bet kurio iš šių makrokomandų ekvivalentą, kai reikia, bet kada reikia, bet kodėl tai daryti? Atminkite, kad makro pakaitalas vyksta išankstiniame apdorojimo procese, todėl sukurtas kodas atspindi faktą, kad vertintojai vertina, kad vertybės yra pastovios, t.y. Taip pat yra veiksminga naudoti apibendrintus makrokomandas „iš naujo išrasti ratą“ kiekvieną kartą, kai reikia atlikti bitų manipuliavimą.

Įsitikinęs? Štai keletas bandymų kodų - aš naudoju „Watcom C“ pilną optimizavimą ir nenaudojant _cdecl, todėl gautas išardymas būtų kuo švaresnis:

---- [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 (išardytas)] ---------------------------------------------- ---------

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

40
17 сент. Jogejų atsakymas 17 sepų . 2008-09-17 05:04 '08, 5:04 am. 2008-09-17 05:04

Naudokite bitų operatorius: > |

Norėdami nustatyti paskutinį bitą iki 000b :

 foo = foo | 001b 

Jei norite patikrinti paskutinį bitą foo :

 if ( foo  001b ) .... 

Jei norite išvalyti paskutinį bitą foo :

 foo = foo  110b 

Dėl aiškumo aš naudoju XXXb . Jūs tikriausiai dirbsite su „HEX“ vaizdu, priklausomai nuo duomenų struktūros, kurioje paketai bitai.

31
07 сент. Atsakymą pateikia „ Nsanders“ rugsėjo 7 d 2008-09-07 03:45 '08 at 3:45 am 2008-09-07 03:45

Naujokui norėčiau paaiškinti šiek tiek daugiau pavyzdžių:

Pavyzdys:

 value is 0x55; bitnum : 3rd. 

> Operatorius naudojamas bitui patikrinti:

 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) 

Perjungti arba perjungti:

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

| : nustatykite bitą

 0101 0101 | 0000 1000 ___________ 0101 1101 (set the third bit without affecting other bits) 
31
05 июня '12 в 17:18 2012-06-05 17:18 atsakymą pateikė kapildditas birželio 12 d. 12 d. 17:18 2012-06-05 17:18

Čia yra mano mėgstamiausia bitų aritmetinė makrokomanda, kuri veikia bet kokio tipo nepasirašytam sveiko size_t masyvui nuo unsigned char size_t iki size_t (kuris yra didžiausias tipas, kuris turėtų būti veiksmingas darbui):

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

Norėdami nustatyti bitą:

 BITOP(array, bit, |=); 

Jei norite išvalyti bitą:

 BITOP(array, bit, > 

Norėdami perjungti bitą:

 BITOP(array, bit, ^=); 

Norėdami patikrinti bitą:

 if (BITOP(array, bit,  ... 

ir kiti

26
13 июля '10 в 9:53 2010-07-13 09:53 atsakymą pateikė R .. liepos 13 d., 10 d., 9:53, 2010-07-13 09:53

Kadangi tai yra paženklinta, manau, kad naudojate mikrovaldiklį. Visi aukščiau pateikti pasiūlymai galioja ir veikia (skaitymo-modifikavimo, rašymo, sąjungos, struktūros ir kt.).

Tačiau per osciloskopu pagrįstą iššūkį buvau nustebęs, kad šie metodai turi didelę pridėtinę vertę procesoriaus cikle, lyginant su vertės tiesioginiu įrašymu į mikro PORTnSET / PORTnCLEAR registrus, o tai daro tikrą skirtumą ten, kur yra ISR kilpos / aukšto dažnio perjungimo kontaktai .

Tiems, kurie nėra susipažinę: mano pavyzdyje mikro turi bendrą registrą PORTn, kuriame rodomi išvesties kaiščiai, todėl PORTn | = BIT_TO_SET veda prie skaitymo modifikavimo-rašymo į šį registrą. Tačiau „PORTnSET / PORTnCLEAR“ registrai yra „1“, o tai reiškia „prašome padaryti šį bitą 1“ („SET“) arba „prašome padaryti šį bitą nulį“ (CLEAR) ir „0“ reiškia „palikti vieną išėjimą“. taigi, jūs gaunate du prievadus, priklausomai nuo to, ar įdiegėte ar išvalote bitą (ne visada patogu), bet reaguojate daug greičiau ir sumažinate surinktą kodą.

23
14 июня '12 в 18:23 2012-06-14 18:23 Atsakymą pateikė Jonas U birželio 14 d. 12 val. 18:23 PM 2012-06-14 18:23

Taikomas metodas turi ir kitų privalumų įterptoje arenoje. Galite apibrėžti struktūrą, kuri tiesiogiai nukreipia į tam tikros įrangos registro bitus.

 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; 

Turite žinoti bitų pakavimo tvarką: iš pradžių manau, kad tai yra MSB, tačiau tai gali priklausyti nuo įgyvendinimo. Be to, patikrinkite, kaip tvarkyklių laukai tvarkytojai kerta ribas.

Tada galite skaityti, rašyti, išbandyti individualias vertybes, kaip ir anksčiau.

22
06 нояб. atsakymą Roddy pateikė lapkričio 6 d. 2008-11-06 14:30 '08, 14:30, 2008-11-06 14:30

Dažniau pasitaiko savavališko dydžio bitmap vaizdų:

 #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
14 июня '09 в 0:27 2009-06-14 00:27 atsakymas pateikiamas 2008 m. birželio 14 d., 09:27, 00:27

Patikrinkite bitą savavališkoje vietoje savavališko tipo kintamajame:

 #define bit_test(x, y) ( ( ((const char*)  0x80 >> ((y) >> (7-((y) ) ) 

Naudojant pavyzdį:

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

Pastabos: Jis yra sukurtas taip, kad būtų greitas (atsižvelgiant į jo lankstumą) ir nėra šakotas. Tai sukelia efektyvų „SPARC“ kodą rengiant „Sun Studio 8“; Aš taip pat išbandžiau, naudojant MSVC ++ 2008 amd64. Galite sukurti panašias makrokomandas, skirtas nustatyti ir išvalyti bitus. Svarbiausias šio sprendimo skirtumas, palyginti su daugeliu kitų, yra tai, kad jis veikia bet kurioje vietoje beveik bet kokio tipo kintamajame.

18
04 янв. Atsakymą pateikė John Zwinck , sausio 04 d 2009-01-04 02:44 '09 at 2:44 2009-01-04 02:44

Jei darote daug bitų, galite naudoti kaukes, kurios jį pagreitins. Šios funkcijos yra labai sparčios ir lanksčios (jos leidžia sulenkti bet kokio dydžio bitus).

 const unsigned char TQuickByteMask[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, };  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. }  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. }  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. }  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; }  short TIsBitReset( short bit, const unsigned char *bitmap) { return TIsBitSet(bit, bitmap) ^ 1; }  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; } 

Pastaba: norėdami nustatyti „n“ bitą 16 bitų sveikam skaičiui, atlikite šiuos veiksmus:

 TSetBit( n, > 

Jūs turite įsitikinti, kad bitų skaičius yra perduodamos bitų kortelės diapazone. Atkreipkite dėmesį, kad mažų endianų procesorių, ty baitų, žodžių, žodžių, žodžių ir kt. Teisingai parodykite vienas kitą atmintyje (pagrindinė priežastis, kodėl maži endianiniai procesoriai yra geresni nei daugelio procesorių, o aš jaučiu, kad ugnies karas prasideda ...).

14
17 сент. Atsakymą pateikė Tim Ring 17 rugsėjis. 2008-09-17 17:10 '08 at 5:10 pm 2008-09-17 17:10

Ši programa skirta keisti bet kurį duomenų bitą nuo 0 iki 1 arba nuo 1 iki 0:

 { unsigned int data = 0x000000F0; int bitpos = 4; int bitvalue = 1; unsigned int bit = data; bit = (bit>>bitpos) int invbitvalue = 0x00000001 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); } } } 
13
28 февр. atsakymą pateikė Gokul Naathan , vasario 28 d. 2012-02-28 22:27 '12, 22:27 pm 2012-02-28 22:27

Naudokite:

 int ToggleNthBit ( unsigned char n, int num ) { if(num  (1 << n)) num  ~(1 << n); else num |= (1 << n); return num; } 
11
12 апр. Atsakyti thangavel balandžio 12 d 2009-04-12 02:05 '09, 2:05 am. 2009-04-12 02:05

bitset atsako plėtinys:

 #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; } 
10
08 мая '14 в 7:33 2014-05-08 07:33 atsakymą pateikė kendotwill 08 gegužės 14 d. 7:33 2014-05-08 07:33

Jei norite atlikti šią operaciją su „C“ programavimu Linux branduolyje, siūlau naudoti standartines „Linux“ branduolio API.

Žr. 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 

Pastaba Čia visa operacija atliekama vienu žingsniu. Taigi, visi jie garantuojami kaip atominiai, net ir SMP kompiuteriuose, ir naudingi užtikrinant procesorių nuoseklumą.

10
27 мая '16 в 19:41 2016-05-27 19:41 Atsakymą pateikė Jeegar Patel gegužės 27 d., 16 d., 19:41 2016-05-27 19:41

„Visual C 2010“ ir galbūt daugelis kitų kompiliatorių turi tiesioginę paramą įterptųjų bitų operacijoms. Stebėtina, kad jis veikia, net ir operatoriaus () operatorius veikia tinkamai.

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

Taigi, jūsų klausimu IsGph [i] = 1 arba IsGph [i] = 0, supaprastinkite boolų nustatymą ir valymą.

Rasti nenuspausdinamus simbolius ...

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

Atkreipkite dėmesį, kad šis kodas nėra ypatingas. Jis tvarko bitą kaip visumą, kuri techniškai yra. 1 bitų sveikasis skaičius, kuriame gali būti 2 reikšmės ir tik 2 reikšmės.

Kartą naudoju šį metodą, kad galėčiau ieškoti pasikartojančių kredito įrašų, kurių numeris buvo ISAM raktas, naudojant 6 skaitmenų kredito numerį kaip indeksą bitų masyve. Iškart ir iš karto, po 8 mėnesių, įrodiau, kad pagrindinės sistemos, iš kurios mes gavome duomenis, iš tikrųjų yra klaidingos. Bitų masyvų paprastumas užtikrina aukštą pasitikėjimą jų teisingumu - pavyzdžiui, pagal paieškos metodą.

9
30 дек. Atsakymą pateikė vartotojo1899861 30 gruodis. 2012-12-30 05:31 '12 at 5:31 AM 2012-12-30 05:31

Naudokite vieną iš čia apibrėžtų operatorių.

Norėdami nustatyti bitą, naudokite int x = x | 0x?; int x = x | 0x?; kur ? - Tai bitų padėtis dvejetainėje formoje.

6
30 апр. Atsakyti į Jason balandžio 30 d 2012-04-30 09:48 '12 ne 9:48 2012-04-30 09:48

Štai keletas makrokomandų, kurias naudoju:

 SET_FLAG(Status, Flag) ((Status) |= (Flag)) CLEAR_FLAG(Status, Flag) ((Status)  ~(Flag)) INVALID_FLAGS(ulFlags, ulAllowed) ((ulFlags)  ~(ulAllowed)) TEST_FLAGS(t,ulMask, ulBit) (((t) == (ulBit)) IS_FLAG_SET(t,ulMask) TEST_FLAGS(t,ulMask,ulMask) IS_FLAG_CLEAR(t,ulMask) TEST_FLAGS(t,ulMask,0) 
5
07 февр. atsakymą pateikė sam msft 07 Feb. 2015-02-07 02:11 '15 at 2:11 am 2015-02-07 02:11

Kaip nustatyti, išvalyti ir perjungti vieną bitą?

Jei norite išspręsti problemą su bendra kodavimo klaida bandant suformuoti kaukę:
1 nėra pakankamai plati

Kokios problemos kyla, kai number yra platesnis nei 1 ?
x gali būti per didelis, kad būtų galima perkelti 1 << x , o tai lemia neapibrėžtą elgesį (UB). Net jei x nėra per didelis, ~ negali perkelti pakankamai didelių 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 

Apsaugokite 1 pakankamai plačiai:

Kodą galima naudoti 1ull arba pedantiškai (uintmax_t)1 ir optimizuoti kompiliatorių.

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

Arba liejimas - kodavimo / peržiūros / techninės priežiūros klaidos, išlaikant tikslumą ir aktualumą.

 number |= (type_of_number)1 << x; 

Arba švelniai pereikite prie 1 , verčiant matematikos operaciją, kuri yra mažesnė už number tipą.

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

Kaip ir dauguma bitų, geriausia dirbti su nepasirašytomis rūšimis, o ne pasirašytomis.

4
27 сент. atsakymas duotas 27 rugsėjis 2017-09-27 21:18 '17 - 21:18 2017-09-27 21:18

C ++ 11 šablono versija (patalpinta antraštėje):

 namespace bit { template <typename T1, typename T2> inline void set (T1  T2 bit) {variable |= ((T1)1 << bit);} template <typename T1, typename T2> inline void clear(T1  T2 bit) {variable  ~((T1)1 << bit);} template <typename T1, typename T2> inline void flip (T1  T2 bit) {variable ^= ((T1)1 << bit);} template <typename T1, typename T2> inline bool test (T1  T2 bit) {return variable  ((T1)1 << bit);} } namespace bitmask { template <typename T1, typename T2> inline void set (T1  T2 bits) {variable |= bits;} template <typename T1, typename T2> inline void clear(T1  T2 bits) {variable  ~bits;} template <typename T1, typename T2> inline void flip (T1  T2 bits) {variable ^= bits;} template <typename T1, typename T2> inline bool test_all(T1  T2 bits) {return ((variable  bits) == bits);} template <typename T1, typename T2> inline bool test_any(T1  T2 bits) {return variable  bits;} } 
3
10 февр. Joakim L. Christiansen atsakymas vasario 10 d. 2018-02-10 23:07 '18, 23:07 2018-02-10 23:07

Naudojamas kintamasis

 int value, pos; 

vertė - duomenys
pos - pozicijos, kurią norite nustatyti, išvalyti arba perjungti
Nustatykite šiek tiek

 value = value | 1 << pos; 

Išvalyti bitą

 value = value  ~(1 << pos); 

Perjungti bitą

 value = value ^ 1 << pos; 
3
11 июля '18 в 20:32 2018-07-11 20:32 atsakymą pateikė Jeet Parikh liepos 18 d. 18 val. 20.30 val
 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); } 
3
21 февр. atsakymą pateikė Sazzad Hissain Khan , vasario 21 d. 2018-02-21 15:35 '18, 15:35 pm 2018-02-21 15:35

Jei norite nustatyti BitIdx -bitą į Number BitValue

 Number = Number xor (1 shl BitIdx) or (BitValue shl BitIdx) 

Čia apgauti yra pirmiausia besąlygiškai išvalyti BitIdx -bitą, nurodant jį su 1. Ši versija atrodo šiek tiek lėčiau nei su if bit = 1 then setbit else clearbit ( if bit = 1 then setbit else clearbit ), bet yra viena eilutė.

-2
22 мая '17 в 11:24 2017-05-22 11:24 atsakymas pateiktas „ Fr0sT “ gegužės 22 d. 17 val. 11:24

Pabandykite vieną iš šių C funkcijų, kad pakeistumėte n bitus:

 char bitfield; // Start at 0th position void chang_n_bit(int n, int value) { bitfield = (bitfield | (1 << n))  (~( (1 << n) ^ (value << n) )); } 

Or

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

Or

 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; } 
-2
27 мая '14 в 14:46 2014-05-27 14:46 atsakymas buvo pateiktas Vincetui gegužės 14 d. 14, 14:46 2014-05-27 14:46

Kiti klausimai apie „ žymas arba „ Klauskite“