Bitta bitni qanday sozlash, tozalash va almashtirish mumkin?

Qanday qilib biroz o'rnatasiz, tozalaysiz va o'zgartirasiz?


person JeffV    schedule 07.09.2008    source manba
comment
buni o'qing: graphics.stanford.edu/~seander/bithacks.html va, buni o'zlashtirganingizda, buni o'qing: realtimecollisiondetection.net/blog/?p=78   -  person ugasoft    schedule 18.09.2008
comment
Shuningdek, The Bit Twiddler, Bit Twiddling Hacks va Agregat sehrli algoritmlar.   -  person    schedule 05.01.2009


Javoblar (27)


Bir oz sozlash

Bitni o'rnatish uchun bit yo'nalishi bo'yicha OR (|) operatoridan foydalaning.

number |= 1UL << n;

Bu number ning n-bitini o'rnatadi. n nolga teng bo'lishi kerak, agar siz 1-bitni va shunga o'xshashni n-1gacha o'rnatmoqchi bo'lsangiz, n-bitni o'rnatmoqchi bo'lsangiz.

number unsigned long dan kengroq bo'lsa, 1ULL dan foydalaning; 1UL << n ning ko'tarilishi 1UL << n ni baholashdan keyin sodir bo'ladi, bunda long kengligidan kattaroqqa siljish noaniq bo'ladi. Xuddi shu narsa qolgan barcha misollar uchun ham amal qiladi.

Bir oz tozalash

Bir oz tozalash uchun bit bo'yicha AND operatoridan (&) foydalaning.

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

Bu number ning n-bitini tozalaydi. Bit satrni bitli NOT operatori (~) bilan teskari o'zgartirishingiz kerak, keyin esa AND.

Bir oz almashtirish

XOR operatoridan (^) biroz almashtirish uchun foydalanish mumkin.

number ^= 1UL << n;

Bu number ning n-bitini almashtiradi.

Biroz tekshirilmoqda

Siz buni so'ramagan edingiz, lekin men uni qo'shishim mumkin.

Bir oz tekshirish uchun n raqamini o'ngga, so'ngra bit bo'yicha VA uni:

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

Bu number ning n-bitining qiymatini bit o'zgaruvchisiga qo'yadi.

n-bitni x ga o'zgartirish

nth bitni 1 yoki 0 ga o'rnatishga 2 ni to'ldiruvchi C++ ilovasida quyidagilar orqali erishish mumkin:

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

Agar x 1 bo'lsa, n biti o'rnatiladi va x 0 bo'lsa, o'chiriladi. Agar x boshqa qiymatga ega bo'lsa, siz axlat olasiz. x = !!x uni 0 yoki 1 ga mantiqiylashtiradi.

Buni 2 ning to'ldiruvchini inkor qilish harakatidan mustaqil qilish uchun (bu erda -1 ning barcha bitlari o'rnatilgan, 1 ning to'ldiruvchisi yoki belgisi/kattaligi C++ ilovasidan farqli o'laroq), imzosiz inkordan foydalaning.

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

or

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

Odatda portativ bitni manipulyatsiya qilish uchun imzosiz turlardan foydalanish yaxshi fikr.

or

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

(number & ~(1UL << n)) n-bitni tozalaydi va (x << n) n-bitni x ga o'rnatadi.

Umuman olganda, kodni nusxalash/joylashtirmaslik ham yaxshi fikr, shuning uchun ko'p odamlar preprotsessor makroslaridan foydalanadilar (masalan, hamjamiyat wiki javobi quyida.) yoki qandaydir inkapsulyatsiya.

person Paige Ruten    schedule 07.09.2008
comment
Shuni ta'kidlashni istardimki, bitni sozlash/tozalash uchun mahalliy qo'llab-quvvatlanadigan platformalarda (masalan, AVR mikrokontrollerlari) kompilyatorlar ko'pincha x bo'lganda "myByte |= (1 ‹‹ x)" ni mahalliy bit to'plami/toza ko'rsatmalariga tarjima qiladilar. doimiy, masalan: (1 ‹‹ 5) yoki const unsigned x = 5. - person Aaron; 17.09.2008
comment
bit = raqam & (1 ‹‹ x); Bit _Bool (‹stdbool.h›) turiga ega bo'lmasa, x bit qiymatini bitga qo'ymaydi. Aks holda, bit = !!(raqam & (1 ‹‹ x)); bo'ladi.. - person Chris Young; 16.11.2008
comment
Ushbu turdagi echimlar faqat maqsadli o'zgaruvchi integral turdagi bo'lganda ishlaydi. Massivlar kabi boshqa foydali maqsadli turlar ustida ishlash uchun ko'proq umumiy echimlar ishlab chiqilishi mumkin. - person John Zwinck; 04.01.2009
comment
Bu faqat men, lekin men bitni almashtirish iboralarini qavs ichiga olishni afzal ko'raman (yuqorida @Aaron qilgan narsaga o'xshash). - person Happy Green Kid Naps; 09.05.2013
comment
BTW, agar number int dan kengroq bo'lsa, bu erda bit-fiddling jimgina bajarilmaydi. - person anatolyg; 09.05.2013
comment
Nega oxirgisini bit = (number >> x) & 1 ga almashtirmaysiz - person aaronman; 26.06.2013
comment
@Aaron: x86 mahalliy bit testiga ega va o'rnatish/tozalash/to'ldirish ko'rsatmalariga ham ega - person phuclv; 01.08.2013
comment
Menimcha, yozuvda muammo bor. Aytaylik, menda 0011 (o‘nlik 3) bor va men ikkinchi bit o‘rnatilgan yoki yo‘qligini tekshirmoqchiman, masalan, qalin: 0 0 1 1. Siz qanday murojaat qilasiz? x? Bu sizning belgingizga ko'ra 2-chi yoki 1-bit bo'ladimi, chunki agar u 2-bit bo'lsa, sizning taklifingiz ishlamaydi deb o'ylayman, masalan, siz 1 ni ikki marta o'zgartirib, 100 ni olasiz - bu ikkinchi bitni bermaydi. Men yuqorida aniqladim. Shunday emasmi? - person ; 14.09.2013
comment
1 - int harfi, imzolangan. Shunday qilib, bu erda barcha operatsiyalar imzolangan raqamlarda ishlaydi, bu standartlar bilan yaxshi belgilanmagan. Standartlar ikkita to'ldiruvchini yoki arifmetik siljishni kafolatlamaydi, shuning uchun 1U dan foydalanish yaxshidir. - person Siyuan Ren; 10.12.2013
comment
Anatoligning izohiga aniqlik kiritish uchun o'zgartiruvchisiz 1 doimiysi imzolangan int deb belgilangan. Bu barcha o'zgaruvchilar uchun to'g'ri ishlashi uchun uning o'rniga 1ULL dan foydalaning. - person JonS; 08.07.2014
comment
@JonS o'lchami unsigned long long gacha bo'lgan barcha o'zgaruvchilar uchun... __int128 kabi amalda aniqlangan kengaytmalar bo'lishi mumkin. Juda xavfsiz bo'lish uchun (uintmax_t)1 << x - person M.M; 07.02.2015
comment
Men n-bitni x ga o'zgartirish uchun number = number & ~(1 << n) | (x << n); ni afzal ko'raman. - person jiasli; 24.03.2015
comment
@Jiashuo Li: agar number int dan katta bo'lsa va n int dagi bitlar sonidan katta yoki teng bo'lsa, bu bayonot muvaffaqiyatsiz bo'ladi. Bu holatda hatto aniqlanmagan xatti-harakatlarni ham chaqiradi. number = number & ~((uintmax_t)1 << n) | ((uintmax_t)x << n); umumiy ifoda boʻlib, u number ning barcha oʻlchamlari uchun ishlashi kerak, lekin kichikroq oʻlchamlar uchun yomon va samarasiz kod yaratishi mumkin. - person chqrlie; 24.03.2015
comment
Bitni tekshirish bilan bog'liq: Nima uchun birinchi bitni tekshirish uchun raqam va 0x01, to'rtinchisi uchun raqam va 0x08 va boshqalarni ishlatmaslik kerak. - person Anonymous; 08.04.2015
comment
-x kabi operatsiyalardan foydalanish xavfsiz emas, chunki C standarti imzolangan butun sonlarni (masalan,) belgi-kattalik, birlarni to'ldiruvchi yoki kerakli diapazonni ifodalay oladigan boshqa tizim bo'lishiga imkon beradi, ya'ni -x emas (~x) + 1 bilan bir xil bo'lishi kerak. Bu zamonaviy arxitekturada unchalik katta ish emas, lekin siz yetarlicha aqlli optimallashtiruvchi kompilyator sizning kodingiz bilan nima qilishini hech qachon bilmaysiz. - person Kevin; 18.01.2016
comment
Nima uchun biz ! o'rniga ~ dan foydalanamiz? - person 71GA; 30.01.2017
comment
@Anonim. Biz baribir niqoblardan foydalanamiz, shunda biz bir nechta kengaytmalarni bajarishimiz kerak bo'lsa, aniqmi? Yon eslatma, EBCDIC da katta/kichik harf 1 bit. - person mckenzm; 09.03.2017
comment
Oxirgi misol ikkita to'ldiruvchi vakillikni nazarda tutmaydimi? Bu yomon/ko'chma emasmi, uni nima demoqchi bo'lsangiz? - person Patrick Roberts; 15.06.2017
comment
@71GA: Bitli inkor (~) barcha bitlarni o'zgartiradi, shuning uchun ~0xFFF0FFFF 0x000F0000 bo'ladi. Mantiqiy emas (!) qiymat nolga teng bo'lsa 0 ni yoki qiymat nolga teng bo'lsa 1 ni beradi, shuning uchun !0xFFF0FFFF 0x00000000 bo'ladi. - person Adrian McCarthy; 05.09.2017
comment
@PatrickRoberts: Ha, bu 2 ni to'ldirishni talab qiladi. To‘ldiruvchida -1 0b1111..1110 bo‘ladi. (Hammasi -0). C++ shuningdek, belgi/kattalik butun sonlarini ko'rsatishga imkon beradi, bunda -x shunchaki belgi bitini aylantiradi. Men buni ta'kidlash uchun bu javobni yangiladim. Agar siz faqat 2 ning to'ldiruvchi C++ ilovalarini maqsad qilgan bo'lsangiz, bu juda yaxshi. Bu UB emas, u faqat amalga oshirish bilan belgilanadi, shuning uchun 2 ning to'ldiruvchisi sifatida belgilangan imzolangan butun sonlarni amalga oshirishda to'g'ri ishlash talab qilinadi. Bundan tashqari, 1ULL talab qilinishi mumkinligini eslatib, doimiylarni 1UL ga o'zgartirdim. - person Peter Cordes; 10.11.2017
comment
@Kevin: 2 ning to'ldiruvchisidan foydalanadigan C++ dasturida xavfsiz bo'lishi kafolatlangan. UB emas, balki amalga oshirish aniqlangan. Xavotir oladigan narsa kompilyatorlarni optimallashtirish emas, balki to'ldiruvchi yoki belgi/kattalikka ko'chirishdir. - person Peter Cordes; 10.11.2017
comment
@Peter -x UB, agar x INT_MIN bo'lsa. - person Kevin; 10.11.2017
comment
@Kevin: To'g'ri, -(unsigned long)x bo'lishi kerak, bu ham imzolangan tamsayı ko'rinishini chetlab o'tadi. (imzosiz asos 2 2 ning toʻldiruvchi semantikasiga mos keladi.) Lekin u faqat x 0 yoki 1 boʻlsa toʻgʻri ishlaydi. Esda tutingki, biz n bitini x ga oʻrnatyapmiz. - person Peter Cordes; 11.11.2017
comment
@PeterCordes: Bu mutlaqo oqilona. Ammo ishlab chiquvchi menga bu o'zgarmaslik doimo ushlab turishini aytganida! Haqiqatan ham asabiylashaman. - person Kevin; 11.11.2017
comment
@Kevin: Oxirgi tahririmda imzolangan UB haqida hech qanday eslatma qoldirmaslikka qaror qildim, chunki siz portativ 0U - 1U -› all-ones uchun baribir unsigned dan foydalanmoqchisiz. Endi u qanday ko'rinadi? Javobni oddiy saqlashga harakat qildim. !!x bilan mantiqiylashtirish kerak bo'lishi mumkinligini aytdim. Agar bu mening javobim bo'lsa, men har doim imzosiz foydalanish haqida ko'proq matn kiritishim mumkin edi, lekin men bu eski kanonik javobni saqlab qolaman. (Jeremi, o'zgarishlar sizga yoqadi deb umid qilaman, o'zgartirishlarimni o'z so'zlaringiz bilan yoki 9 yildan keyin aytmoqchi bo'lgan boshqa narsalarni kiritish uchun tahrirlashni xohlashingiz mumkin.) - person Peter Cordes; 11.11.2017
comment
Tahrirlash tarixida n-bit x boʻlimiga boshqa uchinchi tomon tahriri tomonidan qoʻshilganini va birinchi navbatda Jeremining ishi emasligini payqadim. - person Peter Cordes; 11.11.2017
comment
N-bitni x ga o'zgartirish usuli C90 uchun ham amal qiladimi? Va bu javob imzosiz raqamlar uchun ham amal qiladimi? - person avivgood2; 22.04.2020
comment
Men bunga kamdan-kam duch kelganman va har doim set bit to value operatsiyasini bajarish uchun bitta iborani o'ylab topishim kerak degan fikrda bo'lganman. Odatda men apparatda save state + unconditionally set/clear + restore state ni bajaraman. Qanday bo'lmasin, men tasodifan bunga qoqilib qoldim va yuqoridagi ifodani albatta o'g'irlayman. - person sherrellbc; 15.01.2021
comment
number = (number | (1UL << n)) ^ (!x << n) Mantiqiy bo'lmagan va bir oz yo'qni olib tashlash uchun soddalashtirilgan - person Shogan Aversa-Druesne; 18.01.2021
comment
yuqoridagi ifoda ^^^^^ x cheklanmagan bo'lishiga imkon beradi, x 0 yoki rost uchun har qanday musbat son bo'lishi mumkin va 0 va 1 ga bog'lanmagan - person Shogan Aversa-Druesne; 18.01.2021
comment
Ba'zida oddiy if/else-iborasi n-ni x ga o'zgartirganda samaraliroq bo'ladimi, deb o'ylayman. number = (number & ~(1UL << n)) | (x << n); ikkita bitli siljishni, bitta baytni aylantirish, bitta VA, bitta OR va nihoyat bitta topshiriqni yaratmaydi. if (x) { number |= (1 << n); } else { number &= ~(1 << n); } bitta taqqoslashni, bir bitni siljitishni, yoki YOKI yoki VA ni baytni aylantirish bilan, shuningdek, topshiriqni hosil qiladi. Eng yomon holatda 6 va 5 ta operatsiya (bitni tozalash). Bitni o'rnatishda 6 va 4. Ko'proq o'qilishi mumkin. Lekin, ehtimol, ba'zi operatsiyalar qimmatroqdir? - person Smartskaft2; 02.05.2021
comment
@Smartskaft2 muammo shundaki, if/else bilan tarmoqlanish ancha qimmatga tushishi mumkin. Filialni bashorat qilishda xatolikni qidiring yoki bu savolga qarang: stackoverflow.com/q/11227809 - person Angra Mainyu; 03.05.2021
comment
@AngraMainyu filialini bashorat qilishda xatoliklar juda kichik: godbolt.org/z/vascq9Khc agar yechim hatto 1,2 bo'lsa ham. marta tezroq. - person JulianH; 26.05.2021
comment
@JulianH Sinov uchun rahmat. Ammo bu testda bizda filial holatida rost/noto‘g‘ri o‘zgaruvchan o‘zgaruvchan naqsh mavjud bo‘lib, uni filial bashoratchisi birinchi bir necha iteratsiyadan keyin mukammal tarzda bashorat qilishi mumkin. Shunday qilib, test aslida filialni bashorat qilishning muvaffaqiyatsizligini o'lchamaydi. - person Angra Mainyu; 27.05.2021
comment
@AngraMainyu Protsessor siz aytganidek mukammal bashorat qilmaydi, chunki o'zgaruvchan va o'zgarmas x o'rtasida tezlikni oshirish farqi bor, ammo x qiymatini tasodifiylashtirishda if bo'lmagan yechim if-yechimdan ikki baravar tezroq bo'ladi: godbolt.org/z/5aEbKchzf Demak, ha, siz haqsiz, filialni bashorat qilish samaradorlikni pasaytiradi. - person JulianH; 28.05.2021

Standart C++ kutubxonasidan foydalanish: std::bitset<N>.

Yoki Boost versiyasi: boost::dynamic_bitset.

O'zingizni siljitishning hojati yo'q:

#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 versiyasi kompilyatsiya vaqti oʻlchamidagi standart kutubxona bilan solishtirganda ish vaqti oʻlchamidagi bitlar toʻplamiga ruxsat beradi. bitset.

person Martin York    schedule 18.09.2008
comment
+1. Bu std::bitset C tilidan foydalanish mumkin emas, lekin muallif o'z savolini C++, AFAIK bilan belgilaganidek, sizning javobingiz bu erda eng yaxshisidir... std::vector‹bool› boshqa yo'l, agar uni bilsangiz. ijobiy va salbiy tomonlari - person paercebal; 19.09.2008
comment
Yaxshi, Martin! Bitlarni "indekslash" uchun siz hatto enum dan foydalanishingiz mumkin: enum { cEngineOn, cDoorsOpen, cAircoOn }; std::bitset‹ cNBBITS › mybits; mybits[ ceEngineOn ].set(); const bool cbDoorOpen = mybits[ cDoorsOpen ]; ... - person xtofl; 27.09.2008
comment
Bu erdagi javoblar orasida, menimcha, bu bitlarni boshqarishning eng yaxshi usuli ... lekin menimcha, savolning ruhi bitlarni qo'lda qanday boshqarish edi. hali, + ovoz :) - person moogs; 15.10.2008
comment
@paercebal: vector‹bool› unchalik samarali emas, chunki C++ da bool 1 bit oʻrniga toʻliq bayt joy egallaydi… - person andrewdotnich; 13.11.2008
comment
@andrewdotnich: vector‹bool› (afsuski) qiymatlarni bit sifatida saqlaydigan mutaxassislikdir. Qo'shimcha ma'lumot uchun gotw.ca/publications/mill09.htm ga qarang... - person Niklas; 12.12.2008
comment
Ehtimol, hech kim bu haqda eslatib o'tmagan bo'lishi mumkin, chunki u ko'milgan holda belgilangan. Ko'pgina o'rnatilgan tizimlarda siz vabo kabi STLdan qochasiz. Va kuchaytirgichni qo'llab-quvvatlash ko'pchilik o'rnatilgan kompilyatorlar orasida juda kam uchraydigan qushdir. - person Lundin; 18.08.2011
comment
@Lundin: To'g'ri emasligini ko'rsating (STLda ba'zi narsalardan qochish kerak, lekin shunga o'xshash umumiy bayonot faqat umumiydir, std :: bitset yaxshi va undan foydalanish hech qanday xarajat qilmaydi.). Ikkinchi nuqta Boost::dynamic_bitset hech narsaga bog'liq emas va osongina ishlatilishi mumkin. - person Martin York; 18.08.2011
comment
@Martin Bu juda to'g'ri. STL va andozalar kabi maxsus ishlash qotillaridan tashqari, ko'plab o'rnatilgan tizimlar hatto butun standart kutubxonalardan butunlay qochishadi, chunki ularni tekshirish juda qiyin. O'rnatilgan filiallarning aksariyati MISRA kabi standartlarni o'z ichiga oladi, bu statik kodni tahlil qilish vositalarini talab qiladi (har qanday dasturiy ta'minot mutaxassislari nafaqat o'rnatilgan odamlardan emas, balki bunday vositalardan foydalanishlari kerak). Umuman olganda, odamlar butun standart kutubxona bo'ylab statik tahlil qilishdan ko'ra yaxshiroq qilishlari kerak - agar uning manba kodi ular uchun maxsus kompilyatorda mavjud bo'lsa. - person Lundin; 19.08.2011
comment
@Lundin: Sizning bayonotlaringiz juda keng (shuning uchun bahslashish foydasiz). Ishonchim komilki, agar ular haqiqat bo'lsa, men vaziyatlarni topa olaman. Bu mening dastlabki fikrimni o'zgartirmaydi. Ushbu ikkala sinf ham o'rnatilgan tizimlarda foydalanish uchun juda yaxshi (va men ulardan foydalanilganligini bilaman). STL/Boost o'rnatilgan tizimlarda ishlatilmasligi haqidagi dastlabki fikringiz ham noto'g'ri. Ishonchim komilki, ulardan foydalanmaydigan tizimlar va hatto ulardan foydalanadigan tizimlar ham ular oqilona foydalaniladi, lekin ulardan foydalanilmaydi deyish to'g'ri emas (chunki ular ishlatilgan tizimlar mavjud). - person Martin York; 19.08.2011
comment
@jons34yp: SGI hujjatlari ko'proq konusli va odatda cppreferencega qaraganda kamroq xatolarga ega. - person Martin York; 24.04.2013
comment
Mavzu aniq C tilini bildiradi, yo'q C++. Shubhasiz, bu noto'g'ri javob, shuning uchun qanday qilib er yuzida u 120+ ijobiy ovoz oldi?! - person mloskot; 10.09.2013
comment
@mloskot: Savol C++ ni aniq bildiradi. Quyidagi yorliqda qaysi tillar amal qiladi degan savol bor. U 120+ ovoz oldi, chunki savolni o'qiy oladigan odamlar teglar kontekstida to'g'ri baholadilar. :-) Oh. Va bu oddiy. - person Martin York; 11.09.2013
comment
@LokiAstari Men teg noto'g'ri yoki va mavzusi noaniq ekanligini da'vo qilishga jur'at etaman. Bu muhim masala, chunki u SO savollari noaniq bo'lib qolishiga olib keladi, shuning uchun haqiqatan ham foydasiz. - person mloskot; 11.09.2013
comment
Faqat shuni bilamanki, men har safar C++ da yaratilgan biror narsani kompilyatsiya qilishga uringanimda, Boost mening yangi eng yomon dushmanimga aylanadi. Baribir ovoz bergan. - person sudo; 13.08.2014
comment
@9000: Nima uchun? Boost bilan hech narsa qilmasligingiz kerak. Bu faqat sarlavhali kutubxona va o'rnatishni kuchaytirish paketlarni boshqarish bo'lishi kerak sudo apt-get install boost-devel - person Martin York; 13.08.2014
comment
Savol C/C++ uchun so'ralgan, shuning uchun ikkala dunyoga ham mos kelish uchun menimcha, STL bu erda qo'llanilmaydi. - person Luis Colorado; 30.09.2014
comment
@LuisColorado: Ammo bu haqda gapirmaslik foydalanuvchilar uchun mavjud bo'lgan ma'lumotlarga ega emasligini anglatadi. Gap sizning javobingizni cheklash emas, balki yechimni taqdim etishdir. OP eng yaxshi javobga belgi qo'yish orqali tegishli yoki yo'qligini hal qiladi. Agar bu javob hamjamiyat uchun foydali deb o'ylasangiz, ovoz berishingiz mumkin, agar u jamiyat uchun ahamiyatsiz bo'lsa. - person Martin York; 30.09.2014
comment
@LuisColorado: Men rozi emasman. Bu muammoni boshqalar aytmagan tarzda hal qildi. To'g'ri, bu C++ dan foydalanadigan odamlarning bir qismi uchun edi, ammo savol C++ deb belgilandi va shuning uchun to'g'ri javob. - person Martin York; 02.10.2014
comment
@LokiAstari, va shuning uchun men shunchaki izoh berdim, hech qanday salbiy baho yo'q, boshqa hech narsa ... shunchaki sharh. - person Luis Colorado; 05.10.2014
comment
@MartinYork O'rnatilgan dunyo keng; lekin agar STLdan qochib, uning o'rniga ba'zi konteynerlar va boshqalar o'z-o'zidan yozilsa, kod deyarli unchalik samarali emas va ko'proq xatolarni o'z ichiga oladi. (Men 2000-yillarning boshlarida shunday tizimlardan biri ustida ishlaganman. U yaxshi, maʼlumot-koʻngilochar tizimi oʻrnatilgan edi, lekin bundan 5 yil avval shaxsiy kompyuter resurslariga ega edi.) - person Peter - Reinstate Monica; 22.01.2020
comment
@Peter-ReinstateMonica biz bu erda faqat std::bitset haqida aniq gapiramiz. - person Martin York; 22.01.2020
comment
@MartinYork Men sizning bayonotingizni qo'llab-quvvatlashga harakat qilardim; O'rnatilgan tizimlarda STL/Boost ishlatilmasligi ham noto'g'ri. U ishlatiladi. (Va ba'zida, agar tizim etarlicha qobiliyatga ega bo'lsa va dasturiy ta'minot etarlicha murakkab bo'lsa, aslida STL dan foydalanmaslik xatobo'ladi, chunki muqobil variantlar -- hech qanday generiklar yoki uyda etishtirilgan -- yomonroq. ) - person Peter - Reinstate Monica; 22.01.2020

Boshqa variant - bit maydonlaridan foydalanish:

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

struct bits mybits;

3-bitli maydonni belgilaydi (aslida, bu uchta 1-bitli dala). Bit operatsiyalari endi biroz (haha) soddalashdi:

Bir oz o'rnatish yoki tozalash uchun:

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

Bir oz o'zgartirish uchun:

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

Biroz tekshirish:

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

Bu faqat qattiq o'lchamli bit maydonlari bilan ishlaydi. Aks holda, oldingi postlarda tasvirlangan bit-twiddling usullariga murojaat qilishingiz kerak.

person Ferruccio    schedule 11.09.2008
comment
Men har doim bitfieldlardan foydalanish yomon fikr ekanligini topdim. Bitlarni taqsimlash tartibini (yuqoridan yoki pastdan) nazorat qila olmaysiz, bu esa bir vaqtning o'zida bitdan tashqari qiymatni barqaror/portativ tarzda ketma-ketlashtirishni imkonsiz qiladi. DIY bit arifmetikasini bit maydonlari bilan aralashtirish ham mumkin emas, masalan, bir vaqtning o'zida bir nechta bitlarni sinab ko'radigan niqob yaratish. Siz, albatta, && dan foydalanishingiz mumkin va kompilyator uni to'g'ri optimallashtirishiga umid qilishingiz mumkin... - person R.. GitHub STOP HELPING ICE; 28.06.2010
comment
Bit maydonlari ko'p jihatdan yomon, men bu haqda deyarli kitob yozishim mumkin edi. Aslida men buni deyarli MISRA-C muvofiqligini talab qiladigan bir oz dala dasturi uchun qilishim kerak edi. MISRA-C amalda aniqlangan barcha xatti-harakatlarni hujjatlashtirishni talab qiladi, shuning uchun men bit sohalarida noto'g'ri ketishi mumkin bo'lgan hamma narsa haqida juda insho yozdim. Bit tartibi, endilik, to'ldirish bitlari, to'ldirish baytlari, boshqa turli xil tekislash muammolari, bit maydoniga va bit maydonidan yashirin va aniq turdagi konvertatsiyalar, int ishlatilmasa UB va hokazo. Buning o'rniga, kamroq xatolar va portativ kodlar uchun bitli operatorlardan foydalaning. Bit maydonlari butunlay keraksiz. - person Lundin; 18.08.2011
comment
Ko'pgina til xususiyatlari singari, bit maydonlaridan to'g'ri foydalanish yoki ularni suiiste'mol qilish mumkin. Agar siz bir nechta kichik qiymatlarni bitta intga to'plashingiz kerak bo'lsa, bit maydonlari juda foydali bo'lishi mumkin. Boshqa tomondan, agar siz bit maydonlari haqiqiy o'z ichiga olgan int bilan qanday bog'lanishi haqida taxmin qilishni boshlasangiz, siz shunchaki muammo so'rayapsiz. - person Ferruccio; 18.08.2011
comment
Shunday qilib, bit tartibi o'zboshimchalik bilan va siz mikrokontrollerda alohida bitlarni burish uchun foydalana olmaysizmi? - person endolith; 08.03.2012
comment
@endolith: Bu yaxshi fikr bo'lmaydi. Siz uni ishlashga majbur qilishingiz mumkin, lekin u boshqa protsessorga yoki boshqa kompilyatorga yoki hatto bir xil kompilyatorning keyingi versiyasiga ko'chma bo'lishi shart emas. - person Ferruccio; 09.03.2012
comment
Bu ajoyib. Mening savolim: sizeof(mybits) ni tekshirgandan so'ng, men 12 (ya'ni, uchta ints o'lchami) olaman. Bu xotirada ajratilgan joymi yoki sizeof funksiyasidagi xatomi? - person iGbanam; 29.11.2012
comment
@Yasky - qaysi kompilyatordan foydalanasiz? Men VC++ 11 va Clang 3.1 bilan 4 ball olaman. - person Ferruccio; 29.11.2012
comment
@Ferruccio Men gcc 4.4.5 versiyasidan foydalanmoqdaman - person iGbanam; 29.11.2012
comment
@R. Ikkalasidan ham foydalanish mumkin, struct ni butun son bilan (odatda anonim) union ichiga qo'yish mumkin va hokazo. U ishlaydi. (Men bu eski mavzu btw ekanligini tushunaman) - person Shade; 17.05.2014
comment
@Shade Bit maydoni bitlari bir xil ittifoqdagi boshqa ma'lumotlar turlariga aqlli, bashorat qilinadigan tarzda xaritalashiga kafolat yo'q. Bunday kodlarning barchasi eng yaxshi holatda butunlay portativ bo'lmaydi. - person Lundin; 14.12.2015
comment
@Yasky va Ferruccio bu yondashuv uchun sizeof() ga turlicha javoblar olishlari nafaqat kompilyatorlar, balki apparat vositalarida ham moslik bilan bog'liq muammolarni ko'rsatishi kerak. Biz ba'zan bu muammolarni tillar yoki belgilangan ish vaqtlari bilan hal qildik, deb o'zimizni aldaymiz, lekin bu haqiqatan ham "bu mening mashinamda ishlaydimi?" Siz ko'milgan yigitlar mening hurmatim (va hamdardligim) bor. - person Kelly S. French; 08.12.2016
comment
__attribute__((packed)) ni xohlashingiz mumkin - person ; 28.06.2020

Bit to'plamini boshqarish va tozalash uchun sarlavha faylida belgilangan makroslardan foydalanaman:

/* 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)))
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))
person Community    schedule 04.11.2008
comment
Men bu 5 yillik post ekanligini tushunaman, lekin bu makrolarning hech birida argumentlarni takrorlash yo'q, Dan - person Robert Kelly; 02.10.2013
comment
BITMASK_CHECK(x,y) ((x) & (y)) ((x) & (y)) == (y) bo'lishi kerak, aks holda u multibitli niqobda noto'g'ri natija beradi (masalan, 5 va 3) /*Barcha qabr qazuvchilarga salom :)*/ - person brigadir; 11.12.2014
comment
1 (uintmax_t)1 yoki shunga o'xshash bo'lishi kerak, agar kimdir bu makroslardan long yoki undan kattaroq turdagi foydalanmoqchi bo'lsa - person M.M; 07.02.2015
comment
Yoki 1ULL ko'pgina ilovalarda (uintmax_t) kabi ishlaydi. - person Peter Cordes; 11.11.2017
comment
@brigadir: har qanday bit to'plami yoki barcha bitlar to'plamini tekshirishni xohlayotganingizga bog'liq. Men javobni ikkalasini tavsiflovchi nomlar bilan kiritish uchun yangiladim. - person Peter Cordes; 11.11.2017
comment
BITMASK_CHECK_ALL(x,y) !~((~(y))|(x)) sifatida amalga oshirilishi mumkin - person Handy999; 20.11.2018
comment
@Handy999 De Morgan qonunini qo'llash va !(~(x) & (y)) ni olish uchun qayta tartibga solishdan keyin nima uchun bu ishlayotganini tushunish biroz osonroq. - person Tavian Barnes; 13.08.2019
comment
Bu juda foydali edi, nega men buni oldin sinab ko'rmaganimga hayronman, ayniqsa #define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b)))) // '!!' to make sure this returns 0 or 1 - person William Martens; 16.02.2021

Ba'zan bitlarni ismlash uchun enum dan foydalanishga arziydi:

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

Keyin ismlar dan keyinroq foydalaning. ya'ni yozish

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

o'rnatish, tozalash va sinab ko'rish. Shunday qilib, siz sehrli raqamlarni kodingizning qolgan qismidan yashirasiz.

Bundan tashqari, men Jeremining yechimini ma'qullayman.

person dmckee --- ex-moderator kitten    schedule 08.09.2008
comment
Shu bilan bir qatorda &= ~ o'rniga clearbits() funksiyasini yaratishingiz mumkin. Nega buning uchun enum dan foydalanasiz? Men bular yashirin o'zboshimchalik qiymatiga ega bo'lgan noyob o'zgaruvchilar to'plamini yaratish uchun deb o'yladim, lekin siz har biriga aniq qiymat berasiz. Xo'sh, ularni o'zgaruvchi sifatida belgilashdan qanday foyda bor? - person endolith; 20.12.2011
comment
@endolith: Tegishli konstantalar to'plami uchun enums dan foydalanish c dasturlashda uzoq vaqtga borib taqaladi. Men zamonaviy kompilyatorlarning const short ga nisbatan yagona afzalligi yoki ular aniq guruhlanganligidan shubhalanaman. Va agar siz ularni bitmasklardan boshqaga olishni istasangiz, siz avtomatik raqamlashni olasiz. Albatta, c ++ da ular alohida turlarni hosil qiladi, bu sizga statik xatolarni tekshirish uchun ozgina qo'shimcha imkoniyatlar beradi. - person dmckee --- ex-moderator kitten; 22.12.2011
comment
Bitlarning har bir mumkin bo'lgan qiymatlari uchun doimiyni aniqlamasangiz, siz aniqlanmagan enum konstantalariga kirasiz. Masalan, ThingError|ThingFlag1 uchun enum ThingFlags qiymati qanday? - person Luis Colorado; 30.09.2014
comment
Agar siz ushbu usuldan foydalansangiz, enum konstantalari har doim int turdagi imzolanganligini yodda tuting. Bu yashirin butun sonlarni ko'tarish yoki imzolangan turlarda bitli operatsiyalar tufayli har qanday nozik xatolarga olib kelishi mumkin. thingstate = ThingFlag1 >> 1, masalan, amalga oshirishda aniqlangan xatti-harakatni chaqiradi. thingstate = (ThingFlag1 >> x) << y aniqlanmagan xatti-harakatni chaqirishi mumkin. Va hokazo. Xavfsiz bo'lish uchun har doim imzosiz turga o'tkazing. - person Lundin; 14.12.2015
comment
@Lundin: C++ 11 dan boshlab siz ro'yxatning asosiy turini belgilashingiz mumkin, masalan: enum My16Bits: unsigned short { ... }; - person Aiken Drum; 15.03.2016

snip-c.zip bitops.h dan:

/*
**  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, keling, narsalarni tahlil qilaylik ...

Bularning barchasida muammoga duch kelayotganingiz ko'rinadigan umumiy ifoda "(1L ‹‹ (posn))". Bularning barchasi bitta bitli va har qanday butun son turi bilan ishlaydigan niqob yaratishdir. "Posn" argumenti bitni xohlagan joyni belgilaydi. Agar posn==0 bo'lsa, bu ifoda quyidagicha baholanadi:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

Agar posn==8 bo'lsa, u quyidagicha baholanadi:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

Boshqacha qilib aytadigan bo'lsak, u ko'rsatilgan pozitsiyada 1 bilan 0 maydonini yaratadi. BitClr() makrosidagi yagona qiyin qism, bu erda biz 1 lar maydoniga bitta 0 bitni o'rnatishimiz kerak. Bu tilde (~) operatori bilan belgilangan iboraning 1 ning to‘ldiruvchisi yordamida amalga oshiriladi.

Niqob yaratilgandan so'ng, u siz taklif qilganingizdek, bit va (&), yoki (|) va xor (^) operatorlari yordamida argumentga qo'llaniladi. Niqob uzun turdagi bo'lgani uchun, makroslar char, short, int yoki long larda ham ishlaydi.

Xulosa shuki, bu butun muammolar sinfining umumiy yechimidir. Albatta, har safar kerak bo'lganda ushbu makroslarning har qandayining ekvivalentini aniq niqob qiymatlari bilan qayta yozish mumkin va hatto maqsadga muvofiqdir, lekin nima uchun buni qilish kerak? Esda tutingki, makro almashtirish preprotsessorda sodir bo'ladi va shuning uchun hosil qilingan kod qiymatlar kompilyator tomonidan doimiy deb hisoblanishi haqiqatini aks ettiradi - ya'ni har safar "g'ildirakni qayta ixtiro qilish" uchun umumiy makrolardan foydalanish samaralidir. bit manipulyatsiyasi qiling.

Ishonchsizmi? Mana bir nechta test kodi - men Watcom C-ni to'liq optimallashtirish bilan va _cdecl-dan foydalanmasdan ishlatganman, natijada demontaj imkon qadar toza bo'ladi:

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

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

person yogeesh    schedule 17.09.2008
comment
Bu haqda 2 ta narsa: (1) makroslaringizni ko'rib chiqishda ba'zilar noto'g'ri makroslar argda bitlarni o'rnatgan/tozalaydi/aylantirishi mumkin, ammo hech qanday topshiriq yo'q; (2) test.c to'liq emas; O'ylaymanki, agar siz ko'proq ishlarni bajarsangiz, muammo topasiz (o'quvchi mashqi) - person Dan; 18.10.2008
comment
-1 Bu shunchaki g'alati chalkashlik. Makrolar orqasida til sintaksisini yashirib, hech qachon C tilini qayta ixtiro qilmang, bu juda yomon amaliyot. Keyin ba'zi g'alatiliklar: birinchi navbatda, 1L imzolanadi, ya'ni barcha bit operatsiyalari imzolangan turda amalga oshiriladi. Ushbu makroslarga o'tgan hamma narsa uzoq vaqt davomida imzolangan holda qaytadi. Yaxshi emas. Ikkinchidan, bu kichikroq protsessorlarda juda samarasiz ishlaydi, chunki u operatsiyalar int darajasida bo'lishi mumkin bo'lgan vaqtni uzoq vaqt davomida amalga oshiradi. Uchinchidan, funksiyaga o'xshash makroslar barcha yovuzlikning ildizidir: sizda hech qanday xavfsizlik turi yo'q. Bundan tashqari, hech qanday topshiriq yo'qligi haqidagi oldingi sharh juda to'g'ri. - person Lundin; 18.08.2011
comment
Agar arg long long bo'lsa, bu bajarilmaydi. 1L mumkin bo'lgan eng keng turdagi bo'lishi kerak, shuning uchun (uintmax_t)1 . (Siz 1ull bilan qutulishingiz mumkin) - person M.M; 07.02.2015
comment
Kod o'lchami uchun optimallashtirdingizmi? Intel asosiy protsessorlarida bu funksiya qaytgandan so'ng AX yoki EAX ni o'qiyotganingizda qisman ro'yxatdan o'tish to'xtash joylariga ega bo'lasiz, chunki u EAX ning 8 bitli komponentlarini yozadi. (Bu AMD protsessorlarida yoki qisman registrlarning nomini toʻliq registrdan alohida oʻzgartirmaydigan boshqalarida yaxshi. Haswell/Skylake AL ​​nomini alohida o'zgartirmaydi, lekin AH nomini o'zgartiradi.). - person Peter Cordes; 11.11.2017

Yangi boshlanuvchilar uchun men misol bilan biroz ko'proq tushuntirmoqchiman:

Misol:

value is 0x55;
bitnum : 3rd.

Bitni tekshirish uchun & operatori ishlatiladi:

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)

Oʻzgartirish yoki aylantirish:

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

| operator: bitni o'rnating

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

Bu "ko'milgan" deb belgilangani uchun siz mikrokontrollerdan foydalanyapsiz deb o'ylayman. Yuqoridagi barcha takliflar amal qiladi va ishlaydi (o'qish-o'zgartirish-yozish, uyushmalar, tuzilmalar va boshqalar).

Biroq, osiloskopga asoslangan disk raskadrovka bilan shug'ullanayotganda, bu usullar mikro-ning PORTnSET / PORTnCLEAR registrlariga to'g'ridan-to'g'ri qiymat yozish bilan solishtirganda, protsessor sikllarida sezilarli yukga ega ekanligini ko'rib hayratda qoldim, bu qattiq halqalar / yuqori bo'lgan joylarda haqiqiy farq qiladi. -chastotali ISR ​​ning almashtirish pinlari.

Notanishlar uchun: Mening misolimda mikroda chiqish pinlarini aks ettiruvchi PORTn umumiy pin-holat registriga ega, shuning uchun PORTn |= BIT_TO_SET ni bajarish ushbu registrga o'qish-o'zgartirish-yozishni keltirib chiqaradi. Biroq, PORTnSET / PORTnCLEAR registrlari "iltimos, bu bitni 1 qiling" (SET) yoki "iltimos, bu bitni nolga aylantiring" (CLEAR) va "0" "pinni yolg'iz qoldiring" degan ma'noni bildirish uchun "1" ni oladi. Shunday qilib, siz bitni o'rnatishingiz yoki tozalashingizga qarab ikkita port manziliga ega bo'lasiz (har doim ham qulay emas), lekin juda tezroq reaktsiya va kichikroq yig'ilgan kod.

person John U    schedule 14.06.2012
comment
Micro Coldfire MCF52259 edi, Codewarrior-da C dan foydalangan. Disassembler / asmga qarash foydali mashqdir, chunki u eng oddiy operatsiyani bajarish uchun protsessor o'tishi kerak bo'lgan barcha bosqichlarni ko'rsatadi. ‹br›Shuningdek, biz kritik vaqt oralig‘ida protsessorni o‘zgartirish bo‘yicha boshqa ko‘rsatmalarni ham ko‘rdik – o‘zgaruvchini var %= max_val bilan cheklash har safar bir qator protsessor sikllarini talab qiladi, if(var › max_val)var-=max_val esa faqat foydalanadi. bir nechta ko'rsatmalar. ‹br›Yana bir nechta fokuslar bo‘yicha yaxshi qo‘llanma bu yerda: codeproject.com/Articles/6154/ - person John U; 19.06.2012
comment
Bundan ham muhimi, yordamchi xotira xaritali kiritish-chiqarish registrlari atomik yangilanishlar mexanizmini ta'minlaydi. Agar ketma-ketlik uzilib qolsa, o'qish/o'zgartirish/yozish juda yomon ketishi mumkin. - person Ben Voigt; 22.02.2015
comment
Yodda tutingki, barcha port registrlari volatile sifatida aniqlanadi va shuning uchun kompilyator bunday registrlar ishtirokidagi kodni optimallashtirishni amalga oshira olmaydi. Shuning uchun bunday kodni qismlarga ajratish va uning assembler darajasida qanday ekanligini ko'rish yaxshi amaliyotdir. - person Lundin; 14.12.2015

Mana mening sevimli bit arifmetik makrosim, u unsigned char dan size_t gacha boʻlgan har qanday belgisiz butun massiv uchun ishlaydi (bu bilan ishlashda samarali boʻlishi kerak boʻlgan eng katta tur):

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

Bir oz sozlash uchun:

BITOP(array, bit, |=);

Biroz tozalash uchun:

BITOP(array, bit, &=~);

Bir oz o'zgartirish uchun:

BITOP(array, bit, ^=);

Bir oz sinab ko'rish uchun:

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

va boshqalar.

person R.. GitHub STOP HELPING ICE    schedule 13.07.2010
comment
O'qish yaxshi, lekin mumkin bo'lgan yon ta'sirlardan xabardor bo'lish kerak. Loopda BITOP(array, bit++, |=); dan foydalanish, ehtimol, qo'ng'iroq qiluvchi xohlagan narsani bajarmaydi. - person foraidt; 13.07.2010
comment
Haqiqatdan ham. =) Siz afzal ko'rishingiz mumkin bo'lgan variantlardan biri uni 2 ta makrosga, 1 tasi massiv elementiga murojaat qilish uchun, ikkinchisi esa bitni joyiga o'tkazish uchun, ala BITCELL(a,b) |= BITMASK(a,b); (ikkalasi ham o'lchamni aniqlash uchun argument sifatida a ni oladi, lekin ikkinchisi hech qachon bo'lmaydi) a ni baholang, chunki u faqat sizeof da ko'rinadi). - person R.. GitHub STOP HELPING ICE; 13.07.2010
comment
@R .. Bu javob haqiqatan ham eski, lekin men bu holatda so'ldan ko'ra funktsiyani afzal ko'raman. - person PC Luddite; 23.10.2015
comment
Kichkina: 3-chi (size_t) tarkib faqat % bilan imzosiz matematikani sug'urtalash uchun u erda bo'lganga o'xshaydi. U erda (unsigned) bo'lishi mumkin. - person chux - Reinstate Monica; 27.09.2017
comment
(size_t)(b)/(8*sizeof *(a)) keraksiz ravishda bo'linishdan oldin b ni toraytirishi mumkin. Faqat juda katta bit massivlari bilan bog'liq muammo. Hali ham qiziqarli makro. - person chux - Reinstate Monica; 27.09.2017

Bitfield yondashuvi o'rnatilgan arenada boshqa afzalliklarga ega. Siz ma'lum bir apparat registridagi bitlarga to'g'ridan-to'g'ri mos keladigan tuzilmani belgilashingiz mumkin.

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;

Bitlarni qadoqlash tartibidan xabardor bo'lishingiz kerak - menimcha, bu birinchi navbatda MSB, lekin bu amalga oshirishga bog'liq bo'lishi mumkin. Shuningdek, kompilyatoringiz bayt chegaralarini kesib o'tgan maydonlarni qanday ishlov berishini tekshiring.

Keyin oldingi kabi individual qiymatlarni o'qishingiz, yozishingiz, sinab ko'rishingiz mumkin.

person Roddy    schedule 06.11.2008
comment
Bit-maydonlar haqida deyarli hamma narsa amalga oshirish bilan belgilanadi. Agar siz o'zingizning kompilyatoringiz ularni qanday amalga oshirishi haqidagi barcha tafsilotlarni bilib olsangiz ham, ularni kodingizda ishlatish, albatta, uni portativ bo'lmaydi. - person Lundin; 18.08.2011
comment
@Lundin - To'g'ri, lekin o'rnatilgan tizim bit-fiddling (ayniqsa, mening javobim bilan bog'liq bo'lgan apparat registrlarida) hech qachon foydali portativ bo'lmaydi. - person Roddy; 20.08.2011
comment
Ehtimol, butunlay boshqa protsessorlar orasida emas. Lekin siz uni kompilyatorlar va turli loyihalar o'rtasida ko'chma bo'lishini xohlaysiz. Va umuman apparat bilan bog'liq bo'lmagan juda ko'p o'rnatilgan bit-fiddling mavjud, masalan, ma'lumotlar protokolini kodlash/dekodlash. - person Lundin; 20.08.2011
comment
...va agar siz o'rnatilgan dasturlash uchun bit maydonlaridan foydalanishni odat qilsangiz, X86 kodingiz tezroq va ozg'inroq ishlashini ko'rasiz. Sinovni sindirish uchun butun mashinangiz bo'lgan oddiy mezonlarda emas, balki dasturlar resurslar uchun raqobatlashadigan ko'p vazifali muhitda. CISC afzalligi - asl dizayn maqsadi protsessorlarni avtobuslarga va sekin xotiraga qaraganda tezroq to'ldirish edi. - person ; 16.02.2013

Ixtiyoriy turdagi o'zgaruvchida ixtiyoriy joyda bir oz tekshiring:

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

Namunali foydalanish:

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

Eslatmalar: Bu tezkor (moslashuvchanligi hisobga olingan holda) va tarmoq boʻlmagan boʻlishi uchun moʻljallangan. Sun Studio 8 kompilyatsiya qilinganda samarali SPARC mashina kodiga olib keladi; Men uni amd64 da MSVC++ 2008 yordamida sinab ko'rdim. Bitlarni o'rnatish va tozalash uchun shunga o'xshash makroslarni yaratish mumkin. Ushbu yechimning boshqa ko'plab variantlardan asosiy farqi shundaki, u deyarli har qanday turdagi o'zgaruvchilarda har qanday joy uchun ishlaydi.

person John Zwinck    schedule 03.01.2009

Umuman olganda, ixtiyoriy o'lchamdagi bitmaplar uchun:

#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)))
person bill    schedule 13.06.2009
comment
CHAR_BIT allaqachon limits.h tomonidan belgilangan, siz o'zingizning BITS ni qo'yishingiz shart emas (va aslida bu bilan kodingizni yomonlashtirasiz) - person M.M; 07.02.2015

Ushbu dastur har qanday ma'lumot bitini 0 dan 1 ga yoki 1 dan 0 ga o'zgartirish uchun mo'ljallangan:

{
    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);
        }
    }
}
person Gokul Naathan    schedule 28.02.2012

Buni ishlating:

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

    return num;
}
person Community    schedule 11.04.2009
comment
Xo'sh, u samarasiz dallanishdan foydalanadi. - person asdf; 02.07.2011
comment
@asdf Kompilyatorning vazifasi eng samarali ikkilik faylni chiqarish, dasturchining vazifasi aniq kod yozishdir. - person M.M; 07.02.2015
comment
Bu ma'lum bir bitni sinab ko'rish, sozlash va tozalashning yaxshi namoyishi. Biroq, bu biroz almashtirish uchun juda yomon yondashuv. - person Ben Voigt; 22.02.2015

Agar siz juda ko'p chayqalayotgan bo'lsangiz, hamma narsani tezlashtiradigan niqoblardan foydalanishni xohlashingiz mumkin. Quyidagi funktsiyalar juda tez va hali ham moslashuvchan (ular har qanday o'lchamdagi bit xaritalarida bitni aylantirishga imkon beradi).

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

E'tibor bering, 16 bitli butun sonda "n" bitini o'rnatish uchun quyidagilarni bajaring:

TSetBit( n, &my_int);

Bit raqami siz o'tadigan bit xaritasi oralig'ida bo'lishini ta'minlash sizga bog'liq. E'tibor bering, baytlar, so'zlar, dwords, qwords va hokazolar xotirada bir-biriga to'g'ri mos keladigan kichik endian protsessorlari uchun (asosiy sabab, kichik endian protsessorlari katta endian protsessorlariga qaraganda "yaxshiroq". kuni...).

person Tim Ring    schedule 17.09.2008
comment
Bitta operator bilan amalga oshirilishi mumkin bo'lgan funksiya uchun jadvaldan foydalanmang. TQuickByteMask[n] (1‹‹n) ga ekvivalent. Bundan tashqari, argumentlaringizni qisqa qilish juda yomon fikrdir. / va % aslida bit o'zgarishi/bit bo'yicha emas, balki bo'linish bo'ladi, chunki 2 kuchiga imzolangan bo'linishni bit bo'yicha amalga oshirib bo'lmaydi. Argument turini unsigned int qilishingiz kerak! - person R.. GitHub STOP HELPING ICE; 28.06.2010
comment
Buning nima keragi bor? Bu faqat kodni sekinroq va o'qishni qiyinlashtiradi? Men u bilan bitta afzallik ko'rmayapman. 1u ‹‹ n C dasturchilari uchun o'qish osonroq va umid qilamanki, CPU ko'rsatmasini bitta soat belgisiga tarjima qilish mumkin. Boshqa tomondan, sizning bo'linmangiz, o'ziga xos arxitektura bo'linishni qanchalik yomon ko'rib chiqishiga qarab, taxminan 10 ta belgiga yoki hatto 100 tagacha yomonlikka tarjima qilinadi. Bitmap xususiyatiga kelsak, tezlikni optimallashtirish uchun har bir bit indeksini bayt indeksiga o'tkazadigan qidiruv jadvaliga ega bo'lish mantiqiyroq bo'ladi. - person Lundin; 18.08.2011
comment
Katta/kichik endianga kelsak, big endian butun sonlar va xom ma'lumotlarni (masalan, satrlarni) xuddi shu tarzda: chapdan o'ngga msb dan lsb ga butun bitmap bo'ylab joylashtiradi. Little endian butun sonlarni chapdan o'ngga 7-0, 15-8, 23-18, 31-24 sifatida ko'rsatadi, ammo xom ma'lumotlar hali ham chapdan o'ngga msb dan lsbgacha. Shunday qilib, sizning algoritmingiz uchun qanchalik kichik endian yaxshiroq ekanligi mendan butunlay tashqarida, buning aksi ko'rinadi. - person Lundin; 18.08.2011
comment
@R.. Agar sizning platformangiz eski mikrochip mcu kabi samarali o'zgara olmasa, jadval foydali bo'lishi mumkin, lekin, albatta, namunadagi bo'linish mutlaqo samarasizdir. - person jeb; 18.11.2011

bitset javobni kengaytirish:

#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;
}
person kendotwill    schedule 08.05.2014

Avval bir nechta narsani faraz qilaylik
num = 55 Bit bo'yicha operatsiyalarni bajarish uchun butun son (o'rnatish, olish, tozalash, almashtirish).
n = 4 Bit bo'yicha operatsiyalarni bajarish uchun 0 asoslangan bit pozitsiyasi.

Qanday qilib bir oz olish mumkin?

  1. Raqamning nth bitini olish uchun o'ngga siljish num, n marta. Keyin bit bo'yicha VA & ni 1 bilan bajaring.
bit = (num >> n) & 1;

Bu qanday ishlaydi?

       0011 0111 (55 in decimal)
    >>         4 (right shift 4 times)
-----------------
       0000 0011
     & 0000 0001 (1 in decimal)
-----------------
    => 0000 0001 (final result)

Qanday qilib bir oz o'rnatish kerak?

  1. Raqamning ma'lum bir bitini o'rnatish uchun. Chapga siljish 1 n marta. Keyin num bilan bit bo'yicha YOKI | amalni bajaring.
num |= (1 << n);    // Equivalent to; num = (1 << n) | num;

Bu qanday ishlaydi?

       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
       0001 0000
     | 0011 0111 (55 in decimal)
-----------------
    => 0001 0000 (final result)

Qanday qilib biroz tozalash kerak?

  1. Chapga siljish 1, n marta, ya'ni 1 << n.
  2. Yuqoridagi natija bilan bit bo'yicha to'ldirishni bajaring. Shunday qilib, n-bit o'rnatilmagan bo'lib qoladi va qolgan bit o'rnatiladi, ya'ni ~ (1 << n).
  3. Nihoyat, yuqoridagi natija va num bilan bit bo'yicha VA & amalni bajaring. Yuqoridagi uchta bosqichni birgalikda num & (~ (1 << n)) deb yozish mumkin;

Biroz tozalash uchun qadamlar

num &= (~(1 << n));    // Equivalent to; num = num & (~(1 << n));

Bu qanday ishlaydi?

       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
     ~ 0001 0000
-----------------
       1110 1111
     & 0011 0111 (55 in decimal)
-----------------
    => 0010 0111 (final result)

Qanday qilib biroz o'zgartirish mumkin?

Bir oz almashtirish uchun biz bitli XOR ^ operatoridan foydalanamiz. Bit bo'yicha XOR operatori ikkala operandning mos biti boshqacha bo'lsa, 1 ni baholaydi, aks holda 0 ga baholaydi.

Bu biroz almashtirishni anglatadi, biz XOR operatsiyasini siz o'zgartirmoqchi bo'lgan bit va 1 bilan bajarishimiz kerak.

num ^= (1 << n);    // Equivalent to; num = num ^ (1 << n);

Bu qanday ishlaydi?

  • Agar o'tish uchun bit 0 bo'lsa, 0 ^ 1 => 1.
  • Agar o'tish uchun bit 1 bo'lsa, 1 ^ 1 => 0.
       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
       0001 0000
     ^ 0011 0111 (55 in decimal)
-----------------
    => 0010 0111 (final result)

Tavsiya etilgan o'qish - Bitwise operatori mashqlari

person Pankaj Prakash    schedule 10.06.2019
comment
Batafsil tushuntirish uchun rahmat. Bu yerda BIT Magic uchun amaliyot muammosi uchun havola havola a> - person Chandra Shekhar; 28.12.2019

Visual C 2010 va boshqa ko'plab kompilyatorlar o'rnatilgan mantiqiy operatsiyalarni to'g'ridan-to'g'ri qo'llab-quvvatlaydi. Bitta xuddi mantiqiy kabi ikkita mumkin bo'lgan qiymatga ega, shuning uchun biz mantiqiy qiymatlardan foydalanishimiz mumkin - ular bir bitdan ko'proq joy egallasa ham. ushbu tasvirda xotira. Bu ishlaydi, hatto sizeof() operatori ham to'g'ri ishlaydi.

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

Shunday qilib, sizning savolingizga IsGph[i] =1 yoki IsGph[i] =0 boollarni sozlash va tozalashni osonlashtiring.

Bosib bo'lmaydigan belgilarni topish uchun:

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

E'tibor bering, ushbu kodda "maxsus" narsa yo'q. U bir oz butun songa o'xshaydi - bu texnik jihatdan shunday. 2 ta qiymatni va faqat 2 ta qiymatni saqlashi mumkin bo'lgan 1 bitli butun son.

Bir vaqtlar men ushbu yondashuvdan ikki nusxadagi kredit yozuvlarini topish uchun foydalanganman, bu erda loan_number ISAM kaliti bo'lib, 6 xonali kredit raqamini bit qatoriga indeks sifatida ishlatgan. Vahshiyona tez va 8 oydan so'ng biz ma'lumotlarni olayotgan asosiy kadrlar tizimi aslida noto'g'ri ishlayotganini isbotladi. Bit massivlarining soddaligi ularning to'g'riligiga ishonchni juda yuqori qiladi - masalan, qidiruv yondashuviga nisbatan.

person Community    schedule 30.12.2012
comment
std::bitset haqiqatan ham ko'pchilik kompilyatorlar tomonidan bit sifatida amalga oshiriladi - person galinette; 17.11.2014
comment
@galinette, roziman. #include ‹bitset› sarlavha fayli bu borada yaxshi manba hisoblanadi. Shuningdek, vektor o'lchamini o'zgartirish kerak bo'lganda maxsus vektor‹bool› klassi. C++ STL, 2-nashr, Nikolay M. Josuttis ularni mos ravishda 650 va 281-betlarda to'liq qamrab oladi. C++ 11 std::bitset-ga bir nechta yangi imkoniyatlarni qo'shadi, men uchun tartibsiz konteynerlardagi xesh funksiyasi alohida qiziqish uyg'otadi. E'tibor uchun rahmat! Men miyam siqilgan sharhimni o'chirib tashlamoqchiman. Internetda allaqachon axlat yetarli. Men unga qo'shishni xohlamayman. - person ; 18.11.2014
comment
Bu har bir bool uchun kamida butun bir bayt xotiradan foydalanadi. bool ni amalga oshirish uchun int dan foydalanadigan C89 sozlamalari uchun hatto 4 bayt ham bo'lishi mumkin. - person M.M; 07.02.2015
comment
@MattMcNabb, siz haqsiz. C++ da mantiqiy qiymatni amalga oshirish uchun zarur bo'lgan int turining o'lchami standart tomonidan belgilanmagan. Men bu javobning xato ekanligini bir muncha vaqt oldin tushundim, lekin uni bu erda qoldirishga qaror qildim, chunki odamlar buni foydali deb bilishadi. Bits Galinette sharhidan foydalanishni istaganlar uchun bu erda mening bit kutubxonam kabi juda foydali ... stackoverflow.com/a/16534995/1899861 - person ; 12.02.2015
comment
@RocketRoy: Ehtimol, bu bit operatsiyalariga misol deb da'vo qiladigan jumlani o'zgartirishga arziydi. - person Ben Voigt; 22.02.2015

Agar siz ushbu barcha amallarni Linux yadrosida C dasturlash bilan bajarishni istasangiz, men Linux yadrosining standart API-laridan foydalanishni tavsiya qilaman.

Qarang: 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

Eslatma: Bu erda butun operatsiya bir bosqichda amalga oshiriladi. Shunday qilib, bularning barchasi SMP kompyuterlarida hamatomikbo'lishi kafolatlanadi va protsessorlar o'rtasida uyg'unlikni saqlash uchun foydalidir.

person Jeegar Patel    schedule 27.05.2016

Men foydalanadigan ba'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)&(ulMask)) == (ulBit))
IS_FLAG_SET(t,ulMask)             TEST_FLAGS(t,ulMask,ulMask)
IS_FLAG_CLEAR(t,ulMask)           TEST_FLAGS(t,ulMask,0)
person sam msft    schedule 06.02.2015

Bitta bitni qanday sozlash, tozalash va almashtirish mumkin?

Niqob yaratishga urinayotganda keng tarqalgan kodlash xatosini hal qilish uchun:
1 har doim ham yetarlicha keng emas

number 1 dan kengroq turdagi bo'lsa, qanday muammolar yuzaga keladi?
x 1 << x siljishi uchun juda katta bo'lishi mumkin, bu esa aniqlanmagan xatti-harakatga (UB) olib keladi. x unchalik katta bo'lmasa ham, ~ yetarlicha eng muhim bitlarni aylantira olmasligi mumkin.

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

Sug'urtalash uchun 1 yetarli keng:

Kod 1ull yoki pedantik tarzda (uintmax_t)1 dan foydalanishi va kompilyatorga optimallashtirish imkonini berishi mumkin.

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

Yoki translatsiya - bu translatsiyani to'g'ri va dolzarb saqlash uchun kodlash/ko'rib chiqish/xizmat ko'rsatish muammolarini keltirib chiqaradi.

number |= (type_of_number)1 << x;

Yoki 1 ni eng kamida number turiga teng bo'lgan matematik amalni majburlash orqali muloyimlik bilan targ'ib qiling.

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

Ko'pgina bit manipulyatsiyalarida bo'lgani kabi, imzolangan emas, balki imzosiz turlar bilan ishlash yaxshiroqdir.

person chux - Reinstate Monica    schedule 27.09.2017
comment
Eski savolga qiziqarli qarash! Na number |= (type_of_number)1 << x;, na number |= (number*0 + 1) << x; imzolangan turdagi belgi bitini o'rnatish uchun mos emas... Aslini olganda, number |= (1ull << x); ham mos emas. Buni pozitsiya bo'yicha qilishning ko'chma usuli bormi? - person chqrlie; 28.09.2017
comment
@chqrlie IMO, belgi bitini o'rnatish va UB yoki IDBni siljishlar bilan xavf ostiga qo'ymaslikning eng yaxshi usuli imzosiz turlardan foydalanishdir. Juda ko'chma imzolangan kodi juda o'ralgan va qabul qilinishi mumkin emas. - person chux - Reinstate Monica; 28.09.2017

Ushbu dastur @Jeremyning yuqoridagi yechimiga asoslangan. Agar kimdir tezda o'ynashni xohlasa.

public class BitwiseOperations {

    public static void main(String args[]) {

        setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8]
        clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0]
        toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0]
        checkABit(8,4); // check the 4th bit 1000 -> true 
    }

    public static void setABit(int input, int n) {
        input = input | ( 1 << n-1);
        System.out.println(input);
    }


    public static void clearABit(int input, int n) {
        input = input & ~(1 << n-1);
        System.out.println(input);
    }

    public static void toggleABit(int input, int n) {
        input = input ^ (1 << n-1);
        System.out.println(input);
    }

    public static void checkABit(int input, int n) {
        boolean isSet = ((input >> n-1) & 1) == 1; 
        System.out.println(isSet);
    }
}


Output :
8
0
0
true
person Balaji Boggaram Ramanarayan    schedule 22.04.2020

Bir nechta bitlarni o'zgartirishni qo'llab-quvvatlaydigan shablonli versiya (sarlavha fayliga qo'yilgan) (btw AVR mikrokontrolörlarida ishlaydi):

namespace bit {
  template <typename T1, typename T2>
  constexpr inline T1 bitmask(T2 bit) 
  {return (T1)1 << bit;}
  template <typename T1, typename T3, typename ...T2>
  constexpr inline T1 bitmask(T3 bit, T2 ...bits) 
  {return ((T1)1 << bit) | bitmask<T1>(bits...);}

  /** Set these bits (others retain their state) */
  template <typename T1, typename ...T2>
  constexpr inline void set (T1 &variable, T2 ...bits) 
  {variable |= bitmask<T1>(bits...);}
  /** Set only these bits (others will be cleared) */
  template <typename T1, typename ...T2>
  constexpr inline void setOnly (T1 &variable, T2 ...bits) 
  {variable = bitmask<T1>(bits...);}
  /** Clear these bits (others retain their state) */
  template <typename T1, typename ...T2>
  constexpr inline void clear (T1 &variable, T2 ...bits) 
  {variable &= ~bitmask<T1>(bits...);}
  /** Flip these bits (others retain their state) */
  template <typename T1, typename ...T2>
  constexpr inline void flip (T1 &variable, T2 ...bits) 
  {variable ^= bitmask<T1>(bits...);}
  /** Check if any of these bits are set */
  template <typename T1, typename ...T2>
  constexpr inline bool isAnySet(const T1 &variable, T2 ...bits) 
  {return variable & bitmask<T1>(bits...);}
  /** Check if all these bits are set */
  template <typename T1, typename ...T2>
  constexpr inline bool isSet (const T1 &variable, T2 ...bits) 
  {return ((variable & bitmask<T1>(bits...)) == bitmask<T1>(bits...));}
  /** Check if all these bits are not set */
  template <typename T1, typename ...T2>
  constexpr inline bool isNotSet (const T1 &variable, T2 ...bits) 
  {return ((variable & bitmask<T1>(bits...)) != bitmask<T1>(bits...));}
}

Foydalanish misoli:

#include <iostream>
#include <bitset> // for console output of binary values

// and include the code above of course

using namespace std;

int main() {
  uint8_t v = 0b1111'1100;
  bit::set(v, 0);
  cout << bitset<8>(v) << endl;

  bit::clear(v, 0,1);
  cout << bitset<8>(v) << endl;

  bit::flip(v, 0,1);
  cout << bitset<8>(v) << endl;

  bit::clear(v, 0,1,2,3,4,5,6,7);
  cout << bitset<8>(v) << endl;

  bit::flip(v, 0,7);
  cout << bitset<8>(v) << endl;
}

BTW: Optimizator argumenti (masalan: -O3) kompilyatorga yuborilmasa, constexpr va inline ishlatilmaydi. Kodni https://godbolt.org/ orqali sinab ko'ring va ASM chiqishiga qarang.

person Joakim L. Christiansen    schedule 10.02.2018
comment
Bu kod buzilgan. (Bundan tashqari, nima uchun sizda funktsiya ta'riflaridan keyin ; bor?) - person melpomene; 10.02.2018
comment
@melpomene Kod buzilmagan, men uni sinab ko'rdim. Bu kompilyatsiya qilinmaydi yoki natija noto'g'ri deb aytasizmi? Qo'shimcha ';' haqida Esimda yo'q, ularni olib tashlash mumkin. - person Joakim L. Christiansen; 25.02.2018
comment
E'tibor berganingiz uchun rahmat, bu ((variable & bits) == bits) bo'lishi kerak edi - person Joakim L. Christiansen; 27.02.2018
comment
std::bitsetin c++11 dan foydalaning - person pqnet; 25.10.2019
comment
Afsuski, siz kodni yon tomonga aylantirmasdan ham ko'ra olmaysiz, chunki u juda batafsil. Ehtimol, bir nechta yangi qatorlar yordam beradimi? - person Asteroids With Wings; 22.04.2020

-1 dan foydalanmasdan n-bitni x (bit qiymati) ga o'rnatish

Ba'zan -1 yoki shunga o'xshash nimaga olib kelishiga ishonchingiz komil bo'lmasa, -1 dan foydalanmasdan n-bitni o'rnatishingiz mumkin:

number = (((number | (1 << n)) ^ (1 << n))) | (x << n);

Izoh: ((number | (1 << n) n-bitni 1 ga qo'yadi (bu erda | bit bo'yicha OR ni bildiradi), keyin (...) ^ (1 << n) bilan biz n-bitni 0 ga o'rnatamiz va nihoyat (...) | x << n) bilan biz 0 bo'lgan n-bitni (bit qiymati) x ga o'rnatamiz.

Bu golang da ishlaydi.

person Dominic van der Zypen    schedule 06.02.2021
comment
Bu (number & ~(1 << n)) | (!!x << n) kabi qisqaroq (va ehtimol, kompilyator sizning yechimingizni optimallashtirmasa, samaraliroq) bo'lishi mumkin. - person Will Eccles; 08.05.2021

Bit bo'yicha asosiy operatsiyalarni bajarish uchun C tilidagi tartib:

#define INT_BIT (unsigned int) (sizeof(unsigned int) * 8U) //number of bits in unsigned int

int main(void)
{
    
    unsigned int k = 5; //k is the bit position; here it is the 5th bit from the LSb (0th bit)
    
    unsigned int regA = 0x00007C7C; //we perform bitwise operations on regA
    
    regA |= (1U << k);    //Set kth bit
    
    regA &= ~(1U << k);   //Clear kth bit
    
    regA ^= (1U << k);    //Toggle kth bit
    
    regA = (regA << k) | regA >> (INT_BIT - k); //Rotate left by k bits
    
    regA = (regA >> k) | regA << (INT_BIT - k); //Rotate right by k bits

    return 0;   
}

person lckid2004    schedule 17.03.2021

N bitni o'zgartirish uchun C tilida ushbu funktsiyalardan birini sinab ko'ring:

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;
}
person Vincet    schedule 27.05.2014
comment
value << n aniqlanmagan xatti-harakatlarga olib kelishi mumkin - person M.M; 07.02.2015
comment
UB @M.M gapirayotganidan qochish uchun 1 ni 0x1 yoki 1UL ga o'zgartiring - person KPCT; 18.04.2021

person    schedule
comment
Qaytish turi check_nth_bit bool bo'lishi mumkin. - person Xeverous; 05.05.2020
comment
@Xeverous Ha, bu qo'ng'iroq qiluvchilarning niyatiga bog'liq - person Sazzad Hissain Khan; 05.05.2020