Tek bir biti nasıl ayarlar, temizler ve değiştirirsiniz?


Yanıtlar:


3598

Biraz ayarlama

|Bir bit ayarlamak için bitsel VEYA operatörünü ( ) kullanın.

number |= 1UL << n;

Bu nth bitini ayarlayacaktır number. st bitini nayarlamak istiyorsanız sıfır olmalı 1ve bu biti n-1ayarlamak istiyorsanız, eğer nbit bitini ayarlamak istiyorsanız .

Kullanım 1ULLdurumunda numberdaha geniş olduğu unsigned long; 'nin tanıtımı, a'nın genişliğinden daha fazla kaymanın tanımlanmamış davranışının nerede 1UL << ndeğerlendirildiğine kadar gerçekleşmez . Aynısı tüm diğer örnekler için de geçerlidir.1UL << nlong

Biraz temizleme

&Biraz temizlemek için bitsel AND operatörünü ( ) kullanın.

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

Bu nbiraz temizleyecek number. Bit dizesini bitsel DEĞİL operatörü ( ~) ile ve sonra AND ile ters çevirmelisiniz .

Biraz geçiş yapmak

XOR işleci ( ^) biraz geçiş yapmak için kullanılabilir.

number ^= 1UL << n;

Bu ninci biraz geçiş yapacak number.

Biraz kontrol

Bunu siz istemediniz, ama ben de ekleyebilirim.

Biraz kontrol etmek için, n sayısını sağa, sonra bitsel olarak kaydırın VE:

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

Bu, nth bitinin değerini numberdeğişkene koyacaktır bit.

Değiştirme N inci bit x

2 nbit'in tamamlayıcı C ++ uygulamasında th bit'inin ikisine ya 1da 0aşağıdaki şekilde ayarlanması sağlanabilir:

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

Bit neğer kurulacak xolan 1ve eğer temizlenir xolduğunu 0. xBaşka bir değeri varsa , çöp alırsınız. x = !!x0 veya 1 olarak booleanize eder.

Bunu 2'nin tamamlayıcı olumsuzlama davranışından bağımsız hale getirmek için ( -11'in tamamlayıcısı veya işaret / büyüklük C ++ uygulamasından farklı olarak, tüm bitlerin ayarlandığı yer) imzasız olumsuzlama kullanın.

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

veya

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

Taşınabilir bit manipülasyonu için imzasız tipler kullanmak genellikle iyi bir fikirdir.

veya

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

(number & ~(1UL << n))temizleyecektir ninci biti ve (x << n)ayarlayacaktır niçin inci biti x.

Genel olarak kodu kopyalamamak / yapıştırmamak da genellikle iyi bir fikirdir ve birçok kişi önişlemci makrolarını ( topluluk wiki'sinin daha da aşağıya cevabı gibi ) veya bir tür kapsüllemeyi kullanır.


128
Bit kümesi / temizliği (örn. AVR mikro denetleyicileri) için yerel desteğe sahip platformlarda, derleyiciler genellikle x olduğunda yerel ayar kümesi / net talimatlara çevirir. sabit, ör .: (1 << 5) veya imzasız const x = 5.
Aaron

52
bit = sayı & (1 << x); bit, _Bool (<stdbool.h>) türüne sahip olmadığı sürece, bit x'in değerini bit içine koymaz. Aksi takdirde, bit = !! (sayı & (1 << x)); will ..
Chris Young

23
neden sonuncusunu değiştirmiyorsunbit = (number >> x) & 1
aaronman

42
1intimzalanmış bir değişmez değerdir. Dolayısıyla, buradaki tüm işlemler standartlar tarafından iyi tanımlanmamış işaretli numaralar üzerinde çalışır. Standartlar ikisinin tamamlayıcı veya aritmetik kaymasını garanti etmez, bu nedenle kullanımı daha iyidir 1U.
Siyuan Ren

50
Ben number = number & ~(1 << n) | (x << n);n'inci biti x olarak değiştirmeyi tercih ederim .
jiasli

459

Standart C ++ Kitaplığı kullanma: std::bitset<N>.

Veya Boost versiyonu: boost::dynamic_bitset.

Kendinizi yuvarlamanıza gerek yok:

#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 sürümü, standart bir kitaplık derleme zamanı boyutlu bit kümesine kıyasla çalışma zamanı boyutlu bir bit kümesine izin verir .


34
+1. Bu std :: bitset "C" den kullanılabilir değil, ancak yazar sorusunu "C ++" AFAIK ile etiketlediğinden, cevabınız buradaki en iyisi ... std :: vector <bool> başka bir yol, eğer bir kişi artılarını ve eksilerini
bilirse

23
@andrewdotnich: <bool> vektörü (maalesef) değerleri bit olarak depolayan bir uzmanlıktır. Daha fazla bilgi için gotw.ca/publications/mill09.htm adresine bakın ...
Niklas

71
Belki kimse bundan bahsetmedi çünkü bu etiket gömülü olarak etiketlendi. Çoğu gömülü sistemde veba gibi STL'den kaçınırsınız. Ve destek desteği, çoğu gömülü derleyici arasında fark etmek için çok nadir bir kuştur.
Lundin

17
@Martin Çok doğru. STL ve şablonlar gibi belirli performans katillerinin yanı sıra, birçok gömülü sistem, standart kütüphanelerin tümünü tamamen önler, çünkü doğrulamak için çok acı çekerler. Gömülü dalların çoğu, statik kod analiz araçları gerektiren MISRA gibi standartları benimser (herhangi bir yazılım uzmanı sadece gömülü kişiler değil, btw gibi araçları kullanmalıdır). Genel olarak, kaynak kodu belirli bir derleyicide bile mevcutsa, insanların tüm standart kitaplık üzerinden statik analiz yapmaktan daha iyi işleri vardır.
Lundin

37
@Lundin: İfadeleriniz aşırı geniş (bu nedenle tartışmak işe yaramaz). Eminim ki doğru oldukları durumları bulabilirim. Bu benim ilk noktamı değiştirmez. Bu sınıfların her ikisi de gömülü sistemlerde kullanım için gayet iyi (ve bunların kullanıldığını biliyorum). STL / Boost'un gömülü sistemlerde kullanılmaması konusundaki ilk noktanız da yanlıştır. Eminim onları kullanmayan sistemler vardır ve onları kullanan sistemler bile makul bir şekilde kullanılırlar ama kullanılmadıklarını söylemek doğru değildir (çünkü kullanılan sistemler vardır).
Martin York

248

Diğer seçenek bit alanlarını kullanmaktır:

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

struct bits mybits;

3 bitlik bir alanı tanımlar (aslında, üç tane 1 bitlik felds). Bit işlemleri artık biraz (haha) basitleşiyor:

Biraz ayarlamak veya silmek için:

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

Biraz değiştirmek için:

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

Biraz kontrol ediliyor:

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

Bu yalnızca sabit boyutlu bit alanlarıyla çalışır. Aksi takdirde, önceki yazılarda açıklanan bit döndürme tekniklerine başvurmanız gerekir.


68
Ben her zaman bitfields kullanmak kötü bir fikir buldum. Bitlerin tahsis edilme sırası (üstten veya alttan) üzerinde hiçbir kontrole sahip değilsiniz, bu da değeri bir seferde bit dışında sabit / taşınabilir bir şekilde serileştirmeyi imkansız hale getirir. DIY bit aritmetiğini bit alanlarıyla karıştırmak da imkansızdır, örneğin aynı anda birkaç bit için test yapan bir maske yapmak. Tabii ki && kullanabilirsiniz ve derleyici doğru bir şekilde optimize umuyoruz ...
R. .. GitHub DURDURMAK ICE

34
Bit alanları pek çok yönden kötüdür, neredeyse bir kitap yazabilirim. Aslında bunu neredeyse MISRA-C uyumluluğunu gerektiren biraz alan programı için yapmak zorunda kaldım. MISRA-C, tüm uygulama tanımlı davranışların belgelenmesini zorunlu kılar, bu yüzden bit alanlarında yanlış gidebilecek her şey hakkında oldukça bir deneme yazdım. Bit sırası, endianess, dolgu bitleri, dolgu baytları, diğer çeşitli hizalama sorunları, bit alanına ve bit alanından örtük ve açık tip dönüşümler, int kullanılmıyorsa UB vb. Bunun yerine, daha az hata ve taşınabilir kod için bitsel operatörleri kullanın. Bit alanları tamamen yedeklidir.
Lundin

44
Çoğu dil özelliği gibi, bit alanları da doğru şekilde kullanılabilir veya kötüye kullanılabilir. Birden fazla küçük değeri tek bir int'e paketlemeniz gerekiyorsa, bit alanları çok kullanışlı olabilir. Öte yandan, bit alanlarının gerçek içeren int ile nasıl eşleştiği hakkında varsayımlar yapmaya başlarsanız, sadece sorun istiyorsunuz demektir.
Ferruccio

4
@endolith: Bu iyi bir fikir olmazdı. Çalışmasını sağlayabilirsiniz, ancak farklı bir işlemciye veya farklı bir derleyiciye veya hatta aynı derleyicinin bir sonraki sürümüne taşınabilir olması gerekmez.
Ferruccio

3
@Yasky ve Ferruccio, bu yaklaşım için bir sizeof () öğesine farklı yanıtlar almak, yalnızca derleyiciler arasında değil, donanım genelinde uyumluluk ile ilgili sorunları göstermelidir. Bazen bu sorunları dillerle veya tanımlanmış çalışma zamanlarıyla çözdüğümüzü kandırıyoruz, ancak bu gerçekten 'makinemde çalışacak mı?' Siz yerleşik adamlara saygı duyuyorum (ve sempatiler).
Kelly S. French

181

Bit kümesi işlemek ve temizlemek için bir başlık dosyasında tanımlanan makroları kullanın:

/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b))))        // '!!' to make sure this returns 0 or 1

/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK_ALL(x,y) (((x) & (y)) == (y))   // warning: evaluates y twice
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))

17
Uh, bunun 5 yaşında bir yazı olduğunu fark ettim ama bu makroların hiçbirinde tartışma tekrarı yok, Dan
Robert Kelly

11
BITMASK_CHECK(x,y) ((x) & (y))olmalıdır ((x) & (y)) == (y), aksi takdirde bitli maskesini yanlış sonuç verir (örn. 5vs 3/ * Merhaba tüm mezar kazıcılar için:) * /)
Brigadir

7
1(uintmax_t)1herhangi birinin bu makroları bir longveya daha büyük bir türde kullanmaya çalışması durumunda olması veya benzer olması gerekir
MM

2
BITMASK_CHECK_ALL(x,y)olarak uygulanabilir!~((~(y))|(x))
Handy999

3
@ Handy999 De Morgan yasasını uyguladıktan ve tekrar almak için yeniden düzenledikten sonra neden işe yaradığını görmek biraz daha kolay!(~(x) & (y))
Tavian Barnes

114

Bir kullanarak bazen değer enumiçin isim bitleri:

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

Sonra adları daha sonra kullanın . Yani yaz

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

ayarlamak, temizlemek ve test etmek. Bu şekilde sihirli sayıları kodunuzun geri kalanından gizlersiniz.

Bunun dışında Jeremy'nin çözümünü onaylıyorum.


1
Alternatif olarak, clearbits()yerine bir işlev yapabilirsiniz &= ~. Bunun için neden bir numaralandırma kullanıyorsunuz? Bunların gizli rasgele değeri olan bir dizi benzersiz değişken oluşturmak için olduğunu düşündüm, ancak her birine belirli bir değer atarsınız. Peki onları değişken olarak tanımlamanın yararı nedir?
endolit

4
@endolith: enumİlgili sabitler için s kullanımı c programlamasında uzun bir yol kat eder. Modern derleyicilerle tek avantajı const shortya da her ne olursa olsun açıkça birlikte gruplandırıldığından şüpheleniyorum . Ve onları bitmaskinden başka bir şey için istediğinizde otomatik numaralandırmayı elde edersiniz. Elbette c ++ 'da, size biraz ekstra statik hata kontrolü sağlayan farklı türler de oluştururlar.
dmckee --- eski moderatör yavru kedi

Bitlerin olası değerlerinin her biri için bir sabit tanımlamazsanız, tanımlanmamış enum sabitlerine girersiniz. Örneğin enum ThingFlagsdeğeri nedir ThingError|ThingFlag1?
Luis Colorado

6
Bu yöntemi kullanırsanız, enum sabitlerinin her zaman işaretli türde olduğunu lütfen unutmayın int. Bu, örtülü tamsayı yükseltmesi veya imzalı türlerde bitsel işlemler nedeniyle her türlü ince hataya neden olabilir. thingstate = ThingFlag1 >> 1örneğin, uygulama tanımlı davranışı başlatır. thingstate = (ThingFlag1 >> x) << ytanımlanmamış davranışı tetikleyebilir. Ve bunun gibi. Güvende olmak için her zaman imzasız bir türe atın.
Lundin

1
@Lundin: C ++ 11 itibariyle, bir numaralandırmanın temel türünü ayarlayabilirsiniz, örneğin: enum My16Bits: unsigned short { ... };
Aiken Drum

47

Gönderen snip-c.zip 'ler bitops.h:

/*
**  Bit set, clear, and test operations
**
**  public domain snippet by Bob Stout
*/

typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

Tamam, bir şeyleri analiz edelim ...

Bunların hepsinde sorun yaşadığınız genel ifade "(1L << (posn))" dir. Tüm bunlar, tek bitli bir maske oluşturmak ve herhangi bir tamsayı türüyle çalışacak. "Posn" bağımsız değişkeni biti istediğiniz konumu belirtir. Posn == 0 ise, bu ifade şu şekilde değerlendirilir:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

Posn == 8 ise, şunları değerlendirir:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

Başka bir deyişle, belirtilen konumda 1 olan 0'lık bir alan oluşturur. Tek zor kısım BitClr () makrosundadır, burada 1'lerin alanına tek bir 0 bit ayarlamamız gerekir. Bu, tilde (~) operatörü tarafından belirtilenle aynı ifadenin 1'in tamamlayıcısı kullanılarak gerçekleştirilir.

Maske oluşturulduktan sonra, tam da önerdiğiniz gibi, bitsel ve (&) veya (|) ve xor (^) operatörlerini kullanarak argümana uygulanır. Maske uzun tipte olduğundan, makrolar char, short, int veya long'larda da çalışır.

Sonuç olarak, bunun tüm problem sınıflarına genel bir çözüm olmasıdır. Tabii ki, bu makrolardan herhangi birinin eşdeğerini, her ihtiyacınız olduğunda açık maske değerleriyle yeniden yazmak mümkündür ve neden gereklidir? Unutmayın, makro ikamesi ön işlemcide gerçekleşir ve bu nedenle üretilen kod, değerlerin derleyici tarafından sabit olarak kabul edildiğini yansıtacaktır - yani, her ihtiyacınız olduğunda "tekerleği yeniden icat etmek" için genelleştirilmiş makroları kullanmak kadar etkilidir biraz manipülasyon yapmak.

İkna? İşte bazı test kodu - Watcom C'yi tam optimizasyonla ve _cdecl kullanmadan kullandım, böylece ortaya çıkan sökme mümkün olduğunca temiz olacak:

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

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


3
Bununla ilgili 2 şey: (1) makrolarınızı incelemekte, bazıları yanlış bir şekilde makroların argümanda gerçekte set / clear / flip bitleri olduğuna inanıyor olabilir, ancak herhangi bir atama yoktur; (2) testiniz c. Tamamlanmamıştır; Daha fazla vaka çalıştırırsanız bir sorun bulacağınızdan şüpheleniyorum (okuyucu alıştırması)
Dan

19
-1 Bu sadece garip bir şaşkınlık. C dilini makroların arkasındaki dil sözdizimini gizleyerek asla yeniden icat etmeyin, bu çok kötü bir uygulamadır. Sonra bazı tuhaflıklar: ilk olarak 1L imzalanır, yani tüm bit işlemleri işaretli bir tipte gerçekleştirilir. Bu makrolara geçirilen her şey imzalandığı gibi geri dönecektir. İyi değil. İkincisi, operasyonlar int düzeyinde olabildiğince uzun sürdüğü için daha küçük CPU'larda çok verimsiz çalışacaktır. Üçüncüsü, işlev benzeri makrolar tüm kötülüklerin köküdür: hiçbir tür güvenliğiniz yoktur. Ayrıca, hiçbir ödev hakkında önceki yorum çok geçerlidir.
Lundin

2
Bu başarısız olur argise long long. 1Lmümkün olan en geniş tür olması gerekir (uintmax_t)1. ( 1ull
MM

Kod boyutu için optimizasyon yaptınız mı? Intel ana akım CPU'larında, bu işlev döndükten sonra AX veya EAX'ı okurken kısmi kayıt tezgahları alırsınız, çünkü EAX'in 8 bit bileşenlerini yazar. (AMD CPU'larda veya kısmi kayıtları tam kayıttan ayrı olarak yeniden adlandırmayan diğerlerinde iyidir. Haswell / Skylake, AL'yi ayrı olarak yeniden adlandırmaz, ancak AH'yi yeniden adlandırır. ).
Peter Cordes

37

Bitsel işleçleri kullanın: & |

Son biti ayarlamak için 000b:

foo = foo | 001b

Son biti kontrol etmek için foo:

if ( foo & 001b ) ....

İçindeki son biti temizlemek için foo:

foo = foo & 110b

XXXbAçıklık için kullandım . Bitleri paketlediğiniz veri yapısına bağlı olarak muhtemelen HEX temsili ile çalışacaksınız.


7
C'de ikili gösterim yoktur. İkili tamsayı sabitleri standart olmayan bir uzantıdır.
Lundin

Biraz geçiş yapmak için XOR kullanın:foo = foo ^ MY_MASK
Peter L

Bir maskeyi temizlemek için tersine çevirmek için DEĞİL kullanın:foo = foo & ~MY_MASK
Peter L

32

Yeni başlayanlar için bir örnekle biraz daha açıklamak istiyorum:

Misal:

value is 0x55;
bitnum : 3rd.

&Operatör denetim ikili kullanılır:

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)

Değiştir veya Çevir:

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

| operatör: biti ayarla

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

26

İşte en çok işaretsiz tamsayı dizisi unsigned chariçin size_t(bu ile çalışmak için verimli olması gereken en büyük tip) için çalışan en sevdiğim bit aritmetik makro :

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

Biraz ayarlamak için:

BITOP(array, bit, |=);

Biraz temizlemek için:

BITOP(array, bit, &=~);

Biraz değiştirmek için:

BITOP(array, bit, ^=);

Biraz test etmek için:

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

vb.


5
Okumak güzel ama olası yan etkilerin farkında olunmalıdır. BITOP(array, bit++, |=);Bir döngüde kullanmak büyük olasılıkla arayanın istediği şeyi yapmaz.
foraidt

Aslında. Eğer tercih edebilirsiniz =) Bir varyant dizi elemanı ve yerine biraz kayması diğer adresleme için 2 makrolar 1 içine ayırmaktır, ala BITCELL(a,b) |= BITMASK(a,b);(hem take abağımsız değişken olarak boyutunu belirlemek için, ama ikincisi değerlendirmek asla aberi yalnızca içinde görünür sizeof).
R .. GitHub BUZA YARDIMCI DURDUR

1
@R .. Bu cevap gerçekten eski, ama muhtemelen bu durumda bir makroya bir işlev tercih ederim.
PC Luddite

Minör: 3. (size_t)kadro sadece imzasız matematik ile sigortalanmış gibi görünüyor %. Acaba (unsigned)orada.
chux - Monica'yı

(size_t)(b)/(8*sizeof *(a))Gereksiz daralabilir bbölünmeden önce. Sadece çok büyük bit dizileriyle ilgili bir sorun. Hala ilginç bir makro.
chux - Monica'yı eski durumuna getir

25

Bu "gömülü" olarak etiketlendiğinden, bir mikro denetleyici kullandığınızı varsayacağım. Yukarıdaki önerilerin tümü geçerlidir ve çalışır (okuma-değiştirme-yazma, sendikalar, yapılar vb.).

Bununla birlikte, osiloskop tabanlı bir hata ayıklama sırasında, bu yöntemlerin CPU döngülerinde doğrudan mikroun PORTnSET / PORTnCLEAR kayıtlarına bir değer yazmaya kıyasla önemli bir yükü olduğunu fark ettim. frekansı ISR'nin geçiş pimleri.

Tanıdık olmayanlar için: Benim örneğimde, mikro çıkış pinlerini yansıtan genel bir pin-durumu kaydı PORTn'a sahiptir, bu nedenle PORTn | = BIT_TO_SET yapmak bu yazmacıya bir okuma-değiştirme-yazma ile sonuçlanır. Ancak, PORTnSET / PORTnCLEAR kayıtlarında "lütfen bu bit 1'i yap" (SET) veya "lütfen bu biti sıfır yap" (TEMİZLE) ve "0", "pimi yalnız bırak" anlamına gelir. bu nedenle, biti ayarlamanıza veya temizlemenize (her zaman uygun değil), ancak çok daha hızlı bir reaksiyona ve daha küçük birleştirilmiş koda bağlı olarak iki bağlantı noktası adresiyle sonuçlanırsınız .


Micro, Codewarrior'da C kullanarak Coldfire MCF52259'du. Sökücü / asm'ye bakmak, CPU'nun en temel işlemi yapmak için atması gereken tüm adımları gösterdiği için yararlı bir egzersizdir. <br> Ayrıca, zaman açısından kritik döngülerdeki diğer CPU işaretleme talimatlarını da gördük - var% = max_val yaparak bir değişkeni kısıtlamak, her seferinde bir yığın CPU döngüsüne mal olurken, (var> max_val) var- = max_val yalnızca birkaç talimat. <br> Birkaç püf noktası için iyi bir rehber burada: codeproject.com/Articles/6154/…
John U

Daha da önemlisi, yardımcı bellek eşlemeli G / Ç kayıtları atomik güncellemeler için bir mekanizma sağlar. Sekans kesintiye uğrarsa, okuma / değiştirme / yazma çok kötü olabilir.
Ben Voigt

1
Tüm port kayıtlarının şu şekilde tanımlanacağını volatileve bu nedenle derleyicinin bu kayıtları içeren kod üzerinde herhangi bir optimizasyon yapamayacağını unutmayın. Bu nedenle, bu kodu sökmek ve montajcı seviyesinde nasıl ortaya çıktığını görmek iyi bir uygulamadır.
Lundin

24

Bitfield yaklaşımının gömülü arenada başka avantajları vardır. Belirli bir donanım kaydındaki bitlerle doğrudan eşleşen bir yapı tanımlayabilirsiniz.

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;

Biraz paketleme siparişinin farkında olmalısınız - ilk önce MSB olduğunu düşünüyorum, ancak bu uygulamaya bağlı olabilir. Ayrıca, derleyicinizin alan geçiş bayt sınırlarını nasıl işlediğini de doğrulayın.

Daha sonra tek tek değerleri önceki gibi okuyabilir, yazabilir ve test edebilirsiniz.


2
Bit alanları hakkında hemen hemen her şey uygulama tanımlıdır. Özel derleyicinizin bunları nasıl uyguladığına ilişkin tüm ayrıntıları bulmayı başarsanız bile, bunları kodunuzda kullanmak kesinlikle taşınabilir olmaz.
Lundin

1
@Lundin - Gerçek, ancak gömülü sistem biraz işe yaramaz (özellikle cevabımla ilgili olan donanım kayıtlarında) hiçbir zaman kullanışlı olmayacak.
Roddy

1
Tamamen farklı CPU'lar arasında olmayabilir. Ancak büyük olasılıkla derleyiciler arasında ve farklı projeler arasında taşınabilir olmasını istiyorsunuz. Ve veri protokolü kodlama / kod çözme gibi donanım ile ilgili olmayan çok sayıda gömülü "bit-fiddling" var.
Lundin

... ve gömülü programlama yaparak bit alanlarını kullanma alışkanlığına sahipseniz, X86 kodunuzun daha hızlı ve daha yalın çalıştığını göreceksiniz. Kıyaslamayı ezmek için tüm makineye sahip olduğunuz basit kıstaslarda değil, programların kaynaklar için rekabet ettiği gerçek dünyadaki çoklu görev ortamlarında. Avantajı CISC - orijinal tasarım hedefi CPU'ları otobüslerden ve yavaş bellekten daha hızlı telafi etmekti.

20

Rastgele türdeki bir değişkende rastgele bir konumda biraz kontrol edin:

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

Örnek kullanım:

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

Notlar: Bu, hızlı (esnekliği göz önüne alındığında) ve şubesiz olacak şekilde tasarlanmıştır. Sun Studio 8 derlendiğinde verimli SPARC makine kodu ile sonuçlanır; Ayrıca amd64 üzerinde MSVC ++ 2008 kullanarak test ettik. Bitleri ayarlamak ve temizlemek için benzer makrolar yapmak mümkündür. Bu çözümün diğer pek çok ile karşılaştırılmasındaki temel farkı, hemen hemen her tür değişkente herhangi bir konum için çalışmasıdır.


20

Daha genel, rastgele boyutlu bitmap'ler için:

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

2
CHAR_BITtarafından zaten tanımlanmışsa limits.h, kendi BITSkodunuzu girmenize gerek yoktur (ve aslında kodunuzu daha da kötüleştirirsiniz)
MM

14

Bu program herhangi bir veri bitini 0'dan 1'e veya 1'den 0'a değiştirmektir:

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

14

Çok fazla twiddling yapıyorsanız, her şeyi daha hızlı hale getirecek maskeler kullanmak isteyebilirsiniz. Aşağıdaki işlevler çok hızlıdır ve hala esnektir (her boyuttaki bit haritalarında bit döndürülmesine izin verir).

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

Not, bit 'n' yi 16 bit tamsayı olarak ayarlamak için aşağıdakileri yaparsınız:

TSetBit( n, &my_int);

Bit numarasının geçtiğiniz bit eşlemi aralığında olmasını sağlamak size bağlıdır. Baytlar, kelimeler, dwords, qwords, vb. üzerine ...).


2
Tek bir işleçle uygulanabilecek bir işlev için tablo kullanmayın. TQuickByteMask [n], (1 << n) ile eşdeğerdir. Ayrıca, argümanlarınızı kısaltmak çok kötü bir fikirdir. / Ve% aslında bitshift / bitwise değil, bölünme olacaktır ve 2 gücüyle imzalı bölme bitwise uygulanamaz. Argüman türünü unsigned int yapmalısınız!
R .. GitHub DURDURMA BUZA YARDIMCI

Bunun anlamı nedir? Sadece kodu yavaşlatır ve okumayı zorlaştırır? Onunla tek bir avantaj göremiyorum. 1u << n C programcıları için okunması daha kolaydır ve umarım tek bir saatli CPU işlemine çevrilebilir. Öte yandan, bölümünüz, belirli mimarinin bölünmeyi ne kadar kötü işlediğine bağlı olarak, 10 kenara veya 100 kenara kadar kötü bir şeye çevrilecektir. Bitmap özelliğine gelince, hızı optimize etmek için her bit dizinini bir bayt dizinine çeviren bir arama tablosuna sahip olmak daha anlamlı olacaktır.
Lundin

2
Büyük / küçük endian için, büyük endian tamsayıları ve ham verileri (örneğin dizeler) aynı şekilde eşler: tüm bitmap boyunca soldan sağa msb'den lsb'ye. Küçük endian soldan sağa tam sayıları 7-0, 15-8, 23-18, 31-24 olarak eşleyecek, ancak ham veriler hala soldan sağa msb'den lsb'ye kalacaktır. Bu nedenle, algoritmanız için ne kadar az endianın daha iyi olduğu tamamen benden öte, tam tersi görünüyor.
Lundin

2
@R .. Plattformunuz eski mikroçip mcu'lar gibi verimli bir şekilde kaymazsa, ancak elbette örnekteki bölünme mutlak olarak verimsizse bir tablo yararlı olabilir
mutlak

12

Bunu kullan:

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

    return num;
}

5
Verimsiz dallanma kullanır.
asdf

3
@asdf Derleyicinin işi en verimli ikili çıktıyı, programcının işi net kod yazmaktır
MM

3
Bu, belirli bir bitin test edilmesi, ayarlanması ve temizlenmesi için iyi bir örnektir. Ancak bu biraz geçiş yapmak için çok kötü bir yaklaşım.
Ben Voigt

10

bitsetCevabı genişletmek :

#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

Tüm bu işlemleri Linux çekirdeğinde C programlama ile gerçekleştirmek istiyorsanız, Linux çekirdeğinin standart API'lerini kullanmanızı öneririm.

Bkz. 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

Not: Burada tüm işlem tek bir adımda gerçekleşir. Bu nedenle, tüm bunların SMP bilgisayarlarda bile atomik olması garanti edilir ve işlemciler arasında tutarlılığı korumak için kullanışlıdır.


9

Visual C 2010 ve belki de diğer birçok derleyici yerleşik boolean işlemleri için doğrudan desteğe sahiptir. Biraz boole gibi iki olası değere sahiptir, bu yüzden booleanları kullanabiliriz - tek bir bitten daha fazla yer kaplasalar bile bu gösterimde bellek. Bu, sizeof()operatör bile düzgün çalışıyor.

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

Yani, sorunuza IsGph[i] =1, veyaIsGph[i] =0 da ayar ve temizleme bools kolay hale getirmek.

Yazdırılamayan karakterleri bulmak için:

//  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 kod hakkında "özel" bir şey olmadığını unutmayın. Biraz bir tamsayı gibi davranır - teknik olarak öyle. Yalnızca 2 ve 2 değeri alabilen 1 bitlik bir tam sayı.

Bir keresinde bu yaklaşımı, kredi_sayısının ISAM anahtarı olduğu yinelenen kredi kayıtlarını bulmak için, 6 haneli kredi numarasını bit dizisine bir dizin olarak kullanarak kullandım. Savagely hızlı ve 8 ay sonra, verileri almakta olduğumuz ana bilgisayar sisteminin aslında hatalı olduğunu kanıtladı. Bit dizilerinin sadeliği, doğruluklarına olan güveni çok yüksek kılar - örneğin bir arama yaklaşımı.


std :: bitset gerçekten çoğu derleyici tarafından bit olarak uygulanır
galinette

@galinette, Kabul etti. #İnclude <bitset> başlık dosyası bu açıdan iyi bir kaynaktır. Ayrıca, değiştirmek için vektörün boyutuna ihtiyacınız olduğunda özel sınıf vektörü <bool>. C ++ STL, 2. Baskı, Nicolai M. Josuttis bunları sırasıyla 650 ve 281 sayfalarında kapsamlı bir şekilde ele almaktadır. C ++ 11, std :: bitset'e birkaç yeni özellik ekledi, benim için özel ilgi, sıralanmamış kaplarda bir karma işlevidir. Söylediğin için teşekkürler! Beyin kramp yorumumu sileceğim. Zaten web üzerinde yeterince çöp. Buna eklemek istemiyorum.

3
Bu, her biri için en az bir bayt depolama alanı kullanır bool. Hatta intuygulamak için kullanılan C89 kurulumları için 4 bayt bilebool
MM

@MattMcNabb, haklısın. C ++ 'da, bir boolean uygulamak için gereken int türünün boyutu standart tarafından belirtilmez. Bu cevabın bir süre önce hatalı olduğunu fark ettim, ancak insanlar görünüşte faydalı bulduğu için burada bırakmaya karar verdim. Bit galinette'in yorumunu kullanmak isteyenler için burada bit kütüphanem olduğu gibi en yararlı ... stackoverflow.com/a/16534995/1899861

2
@RocketRoy: Muhtemelen bunun "bit işlemleri" nin bir örneği olduğunu iddia eden cümleyi değiştirmeye değer.
Ben Voigt

6

Burada tanımlandığı gibi operatörlerden birini kullanın .

Bir bit ayarlamak için, ikili biçimde bit konumu int x = x | 0x?;nerede kullanılır ?.


2
0xikili değil onaltılı olarak bir değişmezin önekidir.
Ben Voigt

5

İşte kullandığım bazı 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)

5

Kullanılan değişken

int value, pos;

value - Veri
konumu - ayarlamak, silmek veya değiştirmek istediğiniz bitin konumu.

Biraz ayarla:

value = value | 1 << pos;

Biraz temizle:

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

Biraz değiştir:

value = value ^ 1 << pos;

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

Dönüş türü check_nth_bitolabilir bool.
Xeverous

@Xeverous evet bu arayanların niyetine bağlıdır
Sazzad Hissain Khan

5

Diyelim ki ilk önce birkaç şeyin
num = 55 tamsayı işlemleri yapmasını sağlayın (set, get, clear, toggle).
n = 4Bitsel işlemleri gerçekleştirmek için 0 tabanlı bit konumu.

Biraz nasıl alınır?

  1. Almak için nthnum sağ vardiya bit num, nzaman. Ardından bitlerle VE &1 ile gerçekleştirin .
bit = (num >> n) & 1;

Nasıl çalışır?

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

Biraz nasıl ayarlanır?

  1. Belirli bir sayı bitini ayarlamak için. Sola kaydırma 1 nkez. Ardından ile bitsel VEYA |işlemi gerçekleştirin num.
num |= (1 << n);    // Equivalent to; num = (1 << n) | num;

Nasıl çalışır?

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

Nasıl temizlenir?

  1. Sola kaydırma 1, nçarpı yani 1 << n.
  2. Yukarıdaki sonuçla bitsel tamamlayıcı gerçekleştirin. Böylece n'inci bit ayarsız hale gelir ve geri kalan kısım ayarlanmış olur yani~ (1 << n) .
  3. Son olarak, &yukarıdaki sonuç ve ile bitsel VE işlemi gerçekleştirin num. Yukarıdaki üç adım birlikte şöyle yazılabilir num & (~ (1 << n));

Biraz temizleme adımları

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

Nasıl çalışır?

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

Nasıl değiştirilir?

Biraz geçiş yapmak için bitsel XOR ^operatörünü kullanırız. Her iki işlenenin karşılık gelen biti farklıysa, Bitwise XOR operatörü 1 olarak değerlendirilir, aksi takdirde 0 olarak değerlendirilir.

Bu, biraz geçiş yapmak anlamına gelir, geçiş yapmak istediğiniz bit ve 1 ile XOR işlemini gerçekleştirmemiz gerekir.

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

Nasıl çalışır?

  • Değiştirilecek bit 0 ise 0 ^ 1 => 1,.
  • Değiştirilecek bit 1 ise 1 ^ 1 => 0,.
       0000 0001 (1 in decimal)
    <<         4 (left shift 4 times)
-----------------
       0001 0000
     ^ 0011 0111 (55 in decimal)
-----------------
    => 0010 0111 (final result)

Önerilen okuma - Bitsel operatör alıştırmaları


Detaylı açıklama için teşekkürler. İşte BIT Magic link için uygulama problemi için link
Chandra Shekhar

4

Tek bir biti nasıl ayarlar, temizler ve değiştirirsiniz?

Maskeyi oluşturmaya çalışırken yaygın bir kodlama tuzağını ele almak için:
1her zaman yeterince geniş değil

Daha numbergeniş bir tip olduğunda ne gibi problemler olur 1? tanımlanmamış davranışa (UB) yol açan
xdeğişiklik için çok büyük olabilir . Çok büyük olmasa bile , yeterince önemli bitleri çevirmeyebilir.1 << xx~

// 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'in yeterince geniş olmasını sağlamak için:

Kod kullanabilir 1ullveya bilgili bir şekilde kullanabilir (uintmax_t)1ve derleyicinin optimize etmesine izin verebilir .

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

Ya da yayın - kodun doğru ve güncel kalmasını sağlayan kodlama / inceleme / bakım sorunlarını yapar.

number |= (type_of_number)1 << x;

Ya 1da en az onun kadar geniş bir matematik işlemini zorlayarak teşvik edin number.

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

Çoğu bit manipülasyonunda olduğu gibi, imzalı olanlarla değil , imzalanmamış türlerle çalışmak en iyisidir


Eski bir soru üzerine ilginç bir görünüm! İmzalı bir türün işaret bitini ayarlamak için number |= (type_of_number)1 << x;ne number |= (number*0 + 1) << x;uygun ne de ... Aslında, öyle de değil number |= (1ull << x);. Pozisyona göre yapmanın taşınabilir bir yolu var mı?
chqrlie

1
@chqrlie IMO, işaret bitini belirlemekten ve vardiyalı UB veya IDB riskinden kaçınmanın en iyi yolu imzasız türler kullanmaktır . Oldukça portatif vardiya imzalı kod kabul edilemeyecek kadar kıvrıktır.
chux - Monica'yı eski durumuna getir

3

C ++ 11 şablonlu sürüm (başlığa konur):

namespace bit {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bit) {variable |=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bit) {variable ^=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline bool test (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);}
}

namespace bitmask {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bits) {variable |= bits;}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bits) {variable &= ~bits;}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bits) {variable ^= bits;}
    template <typename T1, typename T2> inline bool test_all(T1 &variable, T2 bits) {return ((variable & bits) == bits);}
    template <typename T1, typename T2> inline bool test_any(T1 &variable, T2 bits) {return variable & bits;}
}

Bu kod bozuk. (Ayrıca, ;işlev tanımlarından sonra neden var ?)
melpomene

@melpomene Kod bozuk değil, test ettim. Yani derlemeyecek mi yoksa sonucun yanlış mı olduğunu mu söylüyorsunuz? Ekstra hakkında ';' Hatırlamıyorum, bunlar gerçekten kaldırılabilir.
Joakim L. Christiansen

(variable & bits == bits)?
melpomene

Fark ettiğiniz için teşekkür ederim, olması gerekiyordu((variable & bits) == bits)
Joakim L. Christiansen

std::bitsetc ++ 11'de kullanın
pqnet

0

Bu program @ Jeremy'nin yukarıdaki çözümüne dayanmaktadır. Birisi çabucak oynamak isterse.

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

-2

N bit'i değiştirmek için C dilinde şu işlevlerden birini deneyin:

char bitfield;

// Start at 0th position

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

Veya

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

Veya

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

value << ntanımlanmamış davranışa neden olabilir
MM
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.