Necə bir dəqiqə qurmaq, təmizləmək və dəyişmək?

C / C ++-də bitləri necə quraşdırırsınız, təmizləyirsiniz?

2191
07 сент. JeffV 07 Sentyabr tərəfindən təyin . 2008-09-07 03:42 '08 at 3:42 2008-09-07 03:42
@ 27 cavab

Bitləri qurmaq

Biti təyin etmək üçün bitwise və ya operatoru ( | ) istifadə edin.

 number |= 1UL << n; 

Bu n bitini təyin edəcək. n bit bitini təyin etmək istəyirsinizsə, 1-bit və s n-1 i təyin etmək istəyirsinizsə n sıfır olmalıdır.

1ULL unsigned long çox olduğu halda 1ULL istifadə edin; təqdimat 1UL << n yalnız qiymətləndirmədən sonra baş 1UL << n çünki müəyyənləşdirilməyən davranış long daha çox keçər Eyni digər bütün nümunələrə də aiddir.

Təmizləmə bitləri

Biti təmizləmək üçün bitwise və operatoru ( > ) istifadə edin.

 number  ~(1UL << n); 

Bu n bitini n . Bit simvolunu bitmədən işləməyiniz ( ~ ) operator, sonra isə AND.

Bir az keçin

XOR operatoru ( ^ ) bitləri keçmək üçün istifadə edilə bilər.

 number ^= 1UL << n; 

Bu n bitini dəyişəcək.

Biti yoxlayın

Bunun üçün xahiş etmədi, amma əlavə edə bilərəm.

Bir az yoxlamaq üçün n sayını sağ tərəfə, sonra isə bitsəyə hərəkət edin.

 bit = (number >> n)  1U; 

Bu bir bit dəyişən n bit dəyərini qoyacaqdır.

X-ə nth bitini dəyişin

n bitini 1 və ya 0 təyin etmək C ++-nin 2 əlavəsinin aşağıdakı tətbiqi ilə əldə edilə bilər:

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

x 1 olduqda n bit müəyyən edilir və x 0 olduqda təmizlənir. x xəyali bir məna varsa, zibil olarsınız. x = !!x 0 ya da 1'e boolean.

Bunun əlavə addım-addım 2 add-ons davranışından (1-ci əlavə və ya C ++ işarəsi / dəyəri tətbiqinin fərqli olduğu bütün bitlərin -1 olduğu yerdə), imzalanmamış negativliyi istifadə edin.

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

və ya

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

Portativ bit manipulyasiyası üçün əlverişsiz tipləri istifadə etmək yaxşı bir fikirdir.

Ümumiyyətlə, kodu bir bütün olaraq kopyalamaq / yapışdırmaq yaxşı bir fikirdir və buna görə də bir çox insanlar preprocessor makrolarını (məsələn, aşağıdakı cəmiyyətin wiki-dən cavab ) və ya bir növ encapsulation istifadə edirlər.

3160
07 сент. Jeremy Ruten tərəfindən verilmiş cavab 07 Sep 2008-09-07 03:50 '08 saat 03:50 'da 2008-09-07 03:50

Standart C ++ kitabxanasından istifadə edin: std::bitset<N> .

Və ya Boost : boost::dynamic_bitset .

Özünüzü gəzməyə ehtiyac yoxdur:

 #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; } 
border=0
 [Alpha:] > ./a.out 00010 

Boost versiyası standart bit həddi ilə müqayisədə bit ölçüsünə bit müəyyən etməyə imkan verir.

403
18 сент. Martin York tərəfindən verilmiş cavab Sep 18 2008-09-18 03:34 '08 at 3:34 am 2008-09-18 03:34

Digər variant isə bit sahələrini istifadə etməkdir:

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

3 bitlik bir sahəni təyin edir (əslində, bunlar üç bir bit sahədir). Bit əməliyyatları indi bir qədər asanlaşır (haha):

Bir az qurmaq və ya təmizləmək üçün:

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

Bir az keçmək üçün:

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

Biti yoxlayın:

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

Bu yalnız sabit ölçülü bitfields ilə işləyir. Əks təqdirdə, əvvəlki mesajlarda təsvir edilən bit-twist üsullarına müraciət etməlisiniz.

222
11 сент. Cavab Ferruccio 11 sep tərəfindən verilir . 2008-09-11 03:56 '08 at 3:56 pm 2008-09-11 03:56

Bit setini idarə etmək üçün üstbilgi faylında müəyyən edilmiş makroları istifadə edin:

  #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)) 
136
05 нояб. Cavab Steve Karg tərəfindən 05 noyabr. 2008-11-05 01:35 '08 saat 01:35 2008-11-05 01:35

Bəzən bitləri göstərmək üçün enum istifadə etmək lazımdır:

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

Daha sonra adları istifadə edin. Yazmaq üçün

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

yükləyin, təmizləyin və yoxlayın. Kodunuzun qalan hissəsindən sehrli nömrələri gizlədirsiniz.

Bundan əlavə, Jeremy'nin qərarını dəstəkləyirəm.

104
09 сент. Cavab verildi 09 sentyabr. 2008-09-09 00:07 '08 at 0:07 'da 2008-09-09 00:07

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

Bəli, hər şeyi təhlil etsin ...

Bütün bu hallarda probleminiz olan ümumi ifadə "(1L << (posn))" dir. Bütün bunlar bir bit ilə maska ​​yaradır və hər hansı bir tam ədədlə işləyəcəkdir. "Posn" dəlili bitsin istədiyiniz mövqeyi göstərir. Əgər posn = 0, onda bu ifadə aşağıdakı kimi qiymətləndirilir:

  0000 0000 0000 0000 0000 0000 0000 0001 binary. 

Posn = 8 olarsa, qiymətləndirəcək

  0000 0000 0000 0000 0000 0001 0000 0000 binary. 

Başqa sözlə, sadəcə müəyyən bir vəziyyətdə 1 ilə 0 ədədi yaradır. Yalnız çətin hissə BitClr () makrosundadır, burada 1-ci bitdə bir bit 0 bit təyin etmək lazımdır. Bu, tilde operatoru (~) tərəfindən göstərilən eyni ifadəyə əlavə etməklə əldə edilir.

Bir maska ​​yarandığı andan sonra, bitsel və (və) və ya (|) və xor (^) operatorlarından istifadə edərək, düşündüyünüz kimi eyni şəkildə istifadə olunur. Maska növü uzun olduğundan, makrolar həmçinin char, qısa, int və ya uzun işləyəcək.

Aşağıdakı xətt bu problemlərin bütün sinifinə ümumi bir həlldir. Əlbəttə ki, bu makroların hər hansı birinə bərabər maska ​​dəyərləri ilə bərabər yazmaq mümkündür və hətta həmişə lazım olsa belə mümkündür. Macro əvəzinin əvvəlcədən hazırlayıcıda meydana gəldiyini və buna görə yaradılan kodun dəyərlərin kompilyator tərəfindən sabit olduğunu hesaba çəkəcəklərini yada salın. Hər dəfə bir az manipulyasiya etmək üçün lazım olan "Təkərni yenidən qurmaq" üçün ümumiləşdirilmiş makroları istifadə etmək də təsirlidir.

Söhbət? İşdə bəzi test kodu - tam optimallaşdırma ilə Watcom C istifadə və _cdecl istifadə etmədən, nəticədə sökülməsi mümkün qədər təmiz olardı:

---- [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 (sökülmüş)] ---------------------------------------------- ---------

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

39
17 сент. yogeesh tərəfindən verilmiş cavab 17 sm . 2008-09-17 05:04 '08 saat 05:04 'da 2008-09-17 05:04

Yeniyetmələr üçün bir az daha çox nümunə izah etmək istərdim:

Məsələn:

 value is 0x55; bitnum : 3rd. 

> Operatoru biti yoxlamaq üçün istifadə olunur:

 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 və ya flip:

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

| : bitini təyin edin

 0101 0101 | 0000 1000 ___________ 0101 1101 (set the third bit without affecting other bits) 
31
05 июня '12 в 17:18 2012-06-05 17:18 Cavab kapilddit tərəfindən verilir 05 İyun 2012 at 17:18 2012-06-05 17:18

Bitsel operatorları istifadə edin: > |

Son biti 000b təyin etmək üçün:

 foo = foo | 001b 

foo da son biti yoxlamaq üçün:

 if ( foo  001b ) .... 

foo da son biti təmizləmək üçün:

 foo = foo  110b 

Aydınlıq üçün XXXb istifadə XXXb . Bitsi paketləyən məlumatların strukturuna əsasən, HEX görünüşü ilə işləyəcəksiniz.

30
07 сент. Cavab nsanders tərəfindən Sep 07 2008-09-07 03:45 '08 saat 03:45 'da 2008-09-07 03:45

size_t unsigned char dən size_t (əməliyyat üçün effektiv olması lazım olan ən böyük növü) hər hansı bir işarəsi olmayan tamsayı size_t üçün size_t mənim favorit bit aritmetik size_t :

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

Bit qurmaq üçün:

 BITOP(array, bit, |=); 

Biti təmizləmək üçün:

 BITOP(array, bit, > 

Bir az keçmək üçün:

 BITOP(array, bit, ^=); 

Biti yoxlamaq üçün:

 if (BITOP(array, bit,  ... 

və digərləri

26
13 июля '10 в 9:53 2010-07-13 09:53 Cavab R. tərəfindən verilir . 13 iyul '10 saat 09:53 'da 2010-07-13 09:53

Bu "gömülü" etiketli olduğundan, bir mikrokontrolörün istifadə etdiyini düşünürəm. Yuxarıda göstərilən bütün təkliflər etibarlıdır və işlədir (oxumaq-dəyişdirmək-yazmaq, birlik, quruluşlar və s.).

Lakin, osiloskop əsaslı bir çağırış zamanı mən bu üsulların prosessor dövründə əhəmiyyətli məsafədə olan dəyərini doğrudan mikro PORTnSET / PORTnCLEAR reyestrlərinə yazmaqla müqayisə etdiyinə görə təəccübləndim, bu da ISR loopları / yüksək tezlikli keçid kontakları olduqda real fərq yaradır .

Tövsiyyə etməyənlər üçün: Məsələn, mikro, çıxış pinlərini əks etdirən ümumi qeydiyyatdan keçmiş PORTn, belə ki PORTn | = BIT_TO_SET bu oxuduğuna oxu-yazmağa səbəb olur. Lakin, PORTnSET / PORTnCLEAR qeydləri "1 bit" (SET) və ya "bu bit sıfır edin" (CLEAR) və "bir çıxış" deməkdir "0" deməkdir "1" olaraq təyin edilir. buna görə də, bit yükləməyinizə və ya təmizlənməyinizə (hər zaman rahat deyil) bağlı olaraq iki liman alırsınız, lakin çox daha sürətli reaksiya verin və toplanan kodu azaldın.

23
14 июня '12 в 18:23 2012-06-14 18:23 Cavab John U tərəfindən 14 İyun 2012 tarixində saat 18: 23-də verilir. 2012-06-14 18:23

Daxili yanaşmada tətbiq olunan yanaşma digər üstünlüklərə malikdir. Birbaşa müəyyən bir hardware reyestrində bitlərə birləşdirən bir quruluşu təyin edə bilərsiniz.

 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; 

Bitmə qabiliyyətini bilmək lazımdır: əvvəlcə bu MSB hesab edirəm, amma bu, tətbiqə bağlı ola bilər. Ayrıca, işleyicilerinizin işleyici alanlarının bayt sınırlarını nasıl aşacağına baxın.

Daha sonra oxumaq, yazmaq, fərdi dəyərləri test edə bilərsiniz.

22
06 нояб. Cavab 06 iyul tarixində Roddy tərəfindən verilmişdir. 2008-11-06 14:30 '08 saat 14:30 'da 2008-11-06 14:30

Təsadüfi ölçünün bitmap şəkilləri üçün daha çox ümumi:

 #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 cavab 14 iyun '09 'da 0:27' da verilmişdir 2009-06-14 00:27

Təsadüfi bir növ dəyişən bir qəribə yerdə bit yoxlayın:

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

Məsələn istifadə edin:

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

Qeydlər: Sürətli (rahatlıq verilmişdir) və tarlanmadığı üçün nəzərdə tutulmuşdur. Sun Studio 8 tərtib edərkən bu səmərəli SPARC kodu gətirib çıxarır; Mən həmçinin amd64-də MSVC ++ 2008 istifadə edərək test etdik. Bitləri qurmaq və təmizləmək üçün oxşar makrolar yarada bilərsiniz. Bu həllin əsas fərqi burada əksəriyyətlə müqayisədə demək olar ki, istənilən növ dəyişən hər hansı bir yer üçün çalışır.

18
04 янв. Jan 04-də John Zwinck tərəfindən cavab verilir 2009-01-04 02:44 '09 da 2:44 'da 2009-01-04 02:44

Bir çox biti etsəniz, bütün bunları sürətləndirəcək maskalardan istifadə edə bilərsiniz. Aşağıdakı funksiyalar çox sürətli və hələ də çevikdir (onlar hər hansı bir ölçüdə bitmaplarda bitlərin yığılmasına imkan verir).

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

Qeyd: 'n' bitini 16 bitlik tamsayıya təyin etmək üçün aşağıdakıları yerinə yetirirsiniz:

 TSetBit( n, > 

Bitmə nömrənizin ötürdüyünüz bit kartı daxilində olduğundan əmin olmaq sizə aiddir. Qeyd edək ki, kiçik endian prosessorları üçün baytlar, sözlər, sözlər, sözlər və s. Bir-birlərini yaddaşda düzgün göstərmək (kiçik endian prosessorların çox sayda prosessorlardan daha yaxşı olduğunu əsas səbəbi, amma mən odlu bir müharibənin başladığını hiss edirəm ...).

14
17 сент. Cavab Tim Ring tərəfindən verilib 17 sentyabr. 2008-09-17 17:10 '08 saat 17:10 'da 2008-09-17 17:10

Bu proqram 0-dan 1-ə və ya 1-dən 0-ə qədər hər hansı bir məlumat bitini dəyişdirməyi nəzərdə tutur:

 { 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 февр. Cavab 28 fevralda Gokul Naathan tərəfindən verilir. 2012-02-28 22:27 '12 saat 22:27 'da 2012-02-28 22:27

Bunu istifadə edin:

 int ToggleNthBit ( unsigned char n, int num ) { if(num  (1 << n)) num  ~(1 << n); else num |= (1 << n); return num; } 
11
12 апр. Cavab yaz 12 aprel 2009-04-12 02:05 '09 saat 02.05 'da 2009-04-12 02:05

Bu əməliyyatı Linux çekirdeğinde C proqramlaşdırma ilə yerinə yetirmək istəyirsinizsə , mən standart Linux kernel API'larını istifadə etməyi təklif edirəm.

Https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html səhifəsinə baxın .

 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 

Qeyd Burada bütün əməliyyat bir addımda həyata keçirilir. Beləliklə, onların hamısı SMP kompüterlərində və prosessorlar arasında uyğunluğun təmin edilməsi üçün faydalıdırlar.

10
27 мая '16 в 19:41 2016-05-27 19:41 Cavab Jeegar Patel tərəfindən verilir 27 May '19 , 19:41 2016-05-27 19:41

bitset cavab uzadılması:

 #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 Cavab özotwill tərəfindən verilir 08 May '14 at 7:33 2014-05-08 07:33

Visual C 2010 və bəlkə də bir çox digər tərtibatçı quraşdırılmış bit əməliyyatlarına birbaşa dəstək verir. Şaşırtıcı bir şekilde, hatta sizeof () operatoru düzgün çalışır.

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

Beləliklə, sualınız üçün IsGph [i] = 1 və ya IsGph [i] = 0, boolların qurulmasını və təmizlənməsini asanlaşdırın.

Çarəsiz simvolları tapın ...

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

Bu kodun xüsusi bir şey olmadığını unutmayın. Bu, bütövlükdə bit kimi işləyir, bu da texniki cəhətdəndir. 2 dəyər və yalnız 2 dəyərdən ibarət olan 1 bit tamsayı.

Bir dəfə bu yanaşmanı bir neçə ardıcıllıqda bir endeks olaraq 6 rəqəmli kredit sayını istifadə edərək, num_name bir ISAM anahtarı olduğu yinelenen kredit qeydləri axtarmaq üçün istifadə etdi. 8 aydan sonra dərhal və dərhal məlumatlarımızı əldə etdiyimiz anbar sisteminin əslində səhv olduğunu sübut etdim. Bit-serialların sadəliyi onların düzgünlüyünə güvənir - məsələn, axtarış anlayışı altında.

9
30 дек. Cavab istifadəçi tərəfindən verilir1899861 30 dekabr. 2012-12-30 05:31 '12 at 5:31 AM 2012-12-30 05:31

Burada göstərilən operatorlardan birini istifadə edin.

Biti təyin etmək üçün int x = x | 0x?; int x = x | 0x?; harada ? - İkili formada bit mövqeyi.

6
30 апр. Jason Apr 30'a cavab verin 2012-04-30 09:48 '12 at 9:48 2012-04-30 09:48

Mən istifadə etdiyim bəzi makrolar:

 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 февр. cavab sam msft tərəfindən verilir 07 fevral. 2015-02-07 02:11 '15 at 2:11 am 2015-02-07 02:11

Necə bir dəqiqə qurmaq, təmizləmək və dəyişmək?

Bir maska ​​yaratmaq istəyərkən ümumi bir kodlama səhvi ilə problemi həll etmək üçün:
1 zaman kifayət qədər geniş deyil

Nömrənin 1 dən daha geniş bir növü olduqda hansı problemlər yaranır?
x gətirə biləcək çox böyük ola bilər, bu da müəyyənləşdirilməmiş davranışı (UB) ilə nəticələnir. x çox olmasa da, kifayət qədər əhəmiyyətli bitləri döndərə bilməz.

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

1 kifayət qədər geniş təmin:

Kodu (uintmax_t)1 və ya pedantik (uintmax_t)1 istifadə 1ull və kompilyatoru optimallaşdırmaq olar.

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

Və ya döküm - dəqiqlik və uyğunluq təmin edərkən kodlama / baxış / təmir səhvləri edir.

 number |= (type_of_number)1 << x; 

Ya da number daha kiçik bir riyaziyyat əməliyyatı etməyə məcbur edərək 1 -ə sürün.

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

Çox bit manipulyasiya kimi, imzalanmamış olanları olmayan imza ilə işləmək yaxşıdır.

4
27 сент. cavab çux verilir 27 Sentyabr 2017-09-27 21:18 '17 də 21:18 2017-09-27 21:18

C ++ 11 şablon versiyası (başlığa yerləşdirilib):

 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 февр. 10 fevralda Joakim L. Christiansen tərəfindən verilmiş cavab. 2018-02-10 23:07 '18 saat 23:07 2018-02-10 23:07
 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 февр. cavab 21 fevralda Sazzad Hissain Khan tərəfindən verilir. 2018-02-21 15:35 '18 də 3:35 pm 2018-02-21 15:35

Dəyişənlər

 int value, pos; 

dəyər - məlumatlar
pos - müəyyən etmək, təmizləmək və ya dəyişdirmək istədiyimiz bitin mövqeyi
Bir az qurun

 value = value | 1 << pos; 

Təmiz bit

 value = value  ~(1 << pos); 

Bitməyi bitirin

 value = value ^ 1 << pos; 
3
11 июля '18 в 20:32 2018-07-11 20:32 Cavab Jeet Parik tərəfindən 11 iyul 18: 00-da saat 20: 32-də 2018-07-11 20:32

N bitlərini dəyişdirmək üçün bu C funksiyalarından birini cəhd edin:

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

Və ya

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

Və ya

 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 Cavab Vincet'e 27 May '14 'da 14:46' də veriləcək 2014-05-27 14:46

BitIdx BitValue'da bit BitValue

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

Burada ilk olaraq BitIdx in 1-ci BitIdx qeyd etmək BitIdx . Bu versiya dallanma ilə müqayisədə bir qədər yavaş görünür ( if bit = 1 then setbit else clearbit ), lakin tək xəttdir.

-2
22 мая '17 в 11:24 2017-05-22 11:24 cədvəl 22 may 17-də saat 11: 00-da başlayacaq