आप कैसे सेट, स्पष्ट और थोड़ा टॉगल कर सकते हैं?
आप कैसे सेट, स्पष्ट और थोड़ा टॉगल कर सकते हैं?
जवाबों:
|
बिट सेट करने के लिए बिटवाइज़ OR ऑपरेटर ( ) का उपयोग करें ।
number |= 1UL << n;
वह के n
बिट सेट होगा number
। n
शून्य होना चाहिए, यदि आप 1
सेंट को बिट सेट करना चाहते हैं, तो यदि आप बिट n-1
को सेट करना चाहते हैं n
।
1ULL
यदि उपयोग number
व्यापक है unsigned long
; एक की चौड़ाई से अधिक द्वारा स्थानांतरित करने के लिए अपरिभाषित व्यवहार कहां है, इसका 1UL << n
मूल्यांकन करने के बाद तक प्रचार नहीं होता 1UL << n
है long
। बाकी सभी उदाहरणों पर भी यही बात लागू होती है।
&
थोड़ा साफ करने के लिए बिटवाइज और ऑपरेटर ( ) का उपयोग करें ।
number &= ~(1UL << n);
यही कारण है कि साफ हो जाएगा n
की वें बिट number
। आपको बिटवे नॉट ऑपरेटर ( ~
) के साथ बिट स्ट्रिंग को पलटना होगा , और फिर इसे।
XOR ऑपरेटर ( ^
) का उपयोग थोड़ा टॉगल करने के लिए किया जा सकता है।
number ^= 1UL << n;
कि n
वें बिट के टॉगल होगा number
।
आपने इसके लिए नहीं कहा, लेकिन मैं इसे जोड़ सकता हूं।
एक बिट की जांच करने के लिए, संख्या n को दाईं ओर शिफ्ट करें, फिर बिटवाइज़ और इसे:
bit = (number >> n) & 1U;
यह n
वें बिट के मूल्य number
को चर में डाल देगा bit
।
या n
तो 2 1
या 0
पूरक C ++ कार्यान्वयन पर निम्नलिखित के साथ वें बिट सेट किया जा सकता है:
number ^= (-x ^ number) & (1UL << n);
बिट n
सेट हो जाएगा यदि x
है 1
, और अगर x
है तो साफ़ कर दिया जाएगा 0
। यदि x
कुछ और मूल्य है, तो आपको कचरा मिलता है। x = !!x
यह 0 या 1 के लिए बूलियन करेगा।
इसे 2 के पूरक निषेध व्यवहार से स्वतंत्र करने के लिए (जहां -1
1 बिट के पूरक या संकेत / परिमाण C ++ कार्यान्वयन के विपरीत) सेट किया गया है, अहस्ताक्षरित नकार का उपयोग करें।
number ^= (-(unsigned long)x ^ number) & (1UL << n);
या
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
आमतौर पर पोर्टेबल बिट हेरफेर के लिए अहस्ताक्षरित प्रकारों का उपयोग करना एक अच्छा विचार है।
या
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
साफ हो जाएगा n
वें बिट और (x << n)
सेट हो जाएगा n
करने के लिए वें बिट x
।
यह आमतौर पर एक अच्छा विचार है कि कोड को सामान्य रूप से कॉपी / पेस्ट न किया जाए और इतने सारे लोग प्रीप्रोसेसर मैक्रोज़ (जैसे समुदाय विकी जवाब आगे और नीचे ) या किसी प्रकार के एनकैप्सुलेशन का उपयोग करते हैं।
bit = (number >> x) & 1
1
एक int
शाब्दिक है, जिस पर हस्ताक्षर किए गए हैं। इसलिए यहां सभी ऑपरेशन हस्ताक्षरित संख्याओं पर काम करते हैं, जो मानकों द्वारा अच्छी तरह से परिभाषित नहीं है। मानकों को दो के पूरक या अंकगणितीय बदलाव की गारंटी नहीं है, इसलिए इसका उपयोग करना बेहतर है 1U
।
number = number & ~(1 << n) | (x << n);
n-वें बिट को x में बदलना पसंद करता हूं ।
मानक C ++ लाइब्रेरी का उपयोग करना: std::bitset<N>
:।
या बूस्ट संस्करण:boost::dynamic_bitset
:।
अपना स्वयं का रोल करने की कोई आवश्यकता नहीं है:
#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
बूस्ट संस्करण मानक लाइब्रेरी कंपाइल-टाइम आकार बिटसेट की तुलना में रनटाइम आकार बिटसेट की अनुमति देता है ।
अन्य विकल्प बिट फ़ील्ड का उपयोग करना है:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
3-बिट फ़ील्ड को परिभाषित करता है (वास्तव में, यह तीन 1-बिट फ़ेल्ड है)। बिट संचालन अब थोड़ा सा (हाहा) सरल हो गया है:
थोड़ा सेट या साफ़ करने के लिए:
mybits.b = 1;
mybits.c = 0;
थोड़ा टॉगल करने के लिए:
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
थोड़ा जाँच:
if (mybits.c) //if mybits.c is non zero the next line below will execute
यह केवल निश्चित आकार के बिट फ़ील्ड के साथ काम करता है। अन्यथा आपको पिछली पोस्ट्स में वर्णित बिट-ट्विडलिंग तकनीकों का सहारा लेना होगा।
मैं बिट सेट और स्पष्ट को संभालने के लिए हेडर फ़ाइल में परिभाषित मैक्रोज़ का उपयोग करता हूं:
/* 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))
BITMASK_CHECK(x,y) ((x) & (y))
होना चाहिए ((x) & (y)) == (y)
अन्यथा यह multibit मुखौटा पर गलत परिणाम देता है (उदा। 5
बनाम 3
/ * हैलो सभी कब्र खोदने के लिए:) * /)
1
(uintmax_t)1
अगर किसी को इन मैक्रोज़ को long
बड़े या बड़े प्रकार पर इस्तेमाल करने की कोशिश करनी चाहिए
BITMASK_CHECK_ALL(x,y)
के रूप में लागू किया जा सकता है!~((~(y))|(x))
!(~(x) & (y))
यह कभी-कभी बिट्स के नाम का उपयोग enum
करने के लायक है :
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
फिर बाद में नामों का उपयोग करें । यानी लिखना
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
सेट करने के लिए, स्पष्ट और परीक्षण। इस तरह आप जादू कोड को अपने बाकी कोड से छिपाते हैं।
इसके अलावा मैं जेरेमी के समाधान का समर्थन करता हूं।
clearbits()
इसके बजाय एक समारोह बना सकते हैं &= ~
। आप इसके लिए एनम का उपयोग क्यों कर रहे हैं? मुझे लगता है कि वे छिपे हुए मनमाने मूल्य के साथ अद्वितीय चर का एक गुच्छा बनाने के लिए थे, लेकिन आप प्रत्येक को एक निश्चित मूल्य प्रदान कर रहे हैं। तो क्या लाभ है बनाम सिर्फ उन्हें चर के रूप में परिभाषित करना?
enum
संबंधित स्थिरांक के सेट के लिए s का उपयोग c प्रोग्रामिंग में एक लंबा रास्ता तय करता है। मुझे संदेह है कि आधुनिक कंपाइलरों के साथ const short
या केवल जो भी लाभ है, वह स्पष्ट रूप से एक साथ समूहीकृत है। और जब आप उन्हें बिटमास्क के अलावा किसी और चीज के लिए चाहते हैं तो आपको स्वचालित नंबर मिल जाता है। सी ++ में, वे अलग-अलग प्रकार भी बनाते हैं जो आपको थोड़ा एक्स्ट्रा स्टैटिक एरर चेकिंग देता है।
enum ThingFlags
मूल्य क्या है ThingError|ThingFlag1
?
int
। यह हस्ताक्षरित प्रकारों पर अंतर्निहित पूर्णांक प्रचार या बिटवाइज़ संचालन के कारण सभी प्रकार के सूक्ष्म कीड़े पैदा कर सकता है। thingstate = ThingFlag1 >> 1
उदाहरण के लिए कार्यान्वयन-परिभाषित व्यवहार को लागू करेगा। thingstate = (ThingFlag1 >> x) << y
अपरिभाषित व्यवहार कर सकते हैं। और इसी तरह। सुरक्षित होने के लिए, हमेशा एक अहस्ताक्षरित प्रकार पर जाएं।
enum My16Bits: unsigned short { ... };
/*
** 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)))
ठीक है, चलो चीजों का विश्लेषण करते हैं ...
इन सभी में आपको जो सामान्य अभिव्यक्ति दिख रही है, वह है "(1L << (posn))"। यह सब कुछ एक एकल बिट के साथ एक मुखौटा बनाता है और जो किसी भी पूर्णांक प्रकार के साथ काम करेगा। "पॉज़" तर्क उस स्थिति को निर्दिष्ट करता है जहां आप बिट चाहते हैं। यदि posn == 0 है, तो यह अभिव्यक्ति निम्न का मूल्यांकन करेगी:
0000 0000 0000 0000 0000 0000 0000 0001 binary.
यदि posn == 8, यह निम्न का मूल्यांकन करेगा:
0000 0000 0000 0000 0000 0001 0000 0000 binary.
दूसरे शब्दों में, यह केवल निर्दिष्ट स्थान पर 1 के साथ 0 का क्षेत्र बनाता है। केवल मुश्किल हिस्सा बिटक्लब () मैक्रो में है जहां हमें 1 के क्षेत्र में एक 0 बिट सेट करने की आवश्यकता है। यह टिल्ड (~) ऑपरेटर द्वारा निरूपित के समान अभिव्यक्ति के 1 के पूरक का उपयोग करके पूरा किया जाता है।
एक बार जब मुखौटा बनाया जाता है, तो इसे तर्क पर लागू किया जाता है, जैसा कि आप सुझाव देते हैं, बिटवाइज़ और (()), या (=), और xor (^) ऑपरेटरों के उपयोग से। चूँकि मास्क टाइप लंबा होता है, इसलिए मैक्रोज़ सिर्फ चार, शॉर्ट्स, इंट, या लॉन्ग के पर ही काम करेंगे।
लब्बोलुआब यह है कि यह समस्याओं के एक पूरे वर्ग के लिए एक सामान्य समाधान है। यह निश्चित रूप से, संभव है और यहां तक कि इनमें से किसी भी मैक्रो के समकक्ष को स्पष्ट मुखौटा मूल्यों के साथ हर बार आपको फिर से लिखने की आवश्यकता है, लेकिन ऐसा क्यों? याद रखें, मैक्रो प्रतिस्थापन प्रीप्रोसेसर में होता है और इसलिए उत्पन्न कोड इस तथ्य को प्रतिबिंबित करेगा कि संकलक द्वारा मानों को स्थिर माना जाता है - अर्थात यह सामान्यीकृत मैक्रोज़ का उपयोग करने के लिए उतना ही कुशल है जितना कि "पहिया को सुदृढ़ करना" हर बार आपकी ज़रूरत है थोड़ा हेरफेर करें।
असंतुष्ट? यहां कुछ परीक्षण कोड दिए गए हैं - मैंने पूर्ण अनुकूलन के साथ और बिना एलसीडी का उपयोग किए, ताकि परिणामी विसंक्रमण जितना संभव हो सके:
---- [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 (असंतुष्ट)] -------------------------------------- ---------
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
---- [फिनीस] ------------------------------------------- ----------------------
arg
है तो यह विफल हो जाएगा long long
। 1L
व्यापक संभव प्रकार होने की जरूरत है, इसलिए (uintmax_t)1
। (आप दूर हो सकते हैं 1ull
)
बिटवाइज़ ऑपरेटरों का उपयोग करें: &
|
अंतिम बिट सेट करने के लिए 000b
:
foo = foo | 001b
अंतिम बिट की जाँच करने के लिए foo
:
if ( foo & 001b ) ....
अंतिम बिट को साफ़ करने के लिए foo
:
foo = foo & 110b
मैंने XXXb
स्पष्टता के लिए इस्तेमाल किया । आप संभवतः HEX प्रतिनिधित्व के साथ काम कर रहे होंगे, यह उस डेटा संरचना पर निर्भर करता है जिसमें आप बिट्स पैकिंग कर रहे हैं।
foo = foo ^ MY_MASK
foo = foo & ~MY_MASK
शुरुआत के लिए मैं एक उदाहरण के साथ थोड़ा और व्याख्या करना चाहूंगा:
उदाहरण:
value is 0x55;
bitnum : 3rd.
&
ऑपरेटर प्रयोग किया जाता है बिट की जाँच करें:
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)
टॉगल या फ़्लिप करें:
0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)
|
ऑपरेटर: थोड़ा सेट करें
0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)
यहां मेरा पसंदीदा बिट अंकगणितीय मैक्रो है, जो किसी भी प्रकार के अहस्ताक्षरित पूर्णांक सरणी के लिए काम करता unsigned char
है size_t
(जो कि सबसे बड़ा प्रकार है जिसके साथ काम करने के लिए कुशल होना चाहिए):
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
थोड़ा सेट करने के लिए:
BITOP(array, bit, |=);
थोड़ा साफ करने के लिए:
BITOP(array, bit, &=~);
थोड़ा टॉगल करने के लिए:
BITOP(array, bit, ^=);
थोड़ा परीक्षण करने के लिए:
if (BITOP(array, bit, &)) ...
आदि।
BITOP(array, bit++, |=);
एक लूप में उपयोग करना सबसे अधिक संभावना नहीं है कि कॉलर क्या चाहता है।
BITCELL(a,b) |= BITMASK(a,b);
(दोनों ले a
एक तर्क के रूप आकार निर्धारित करने, लेकिन बाद का मूल्यांकन कभी नहीं होगा a
के बाद से यह केवल में दिखाई देता है sizeof
)
(size_t)
डाली हो केवल कुछ बीमा करने के लिए लग रहे अहस्ताक्षरित गणित के साथ %
। (unsigned)
वहाँ हो सकता है।
(size_t)(b)/(8*sizeof *(a))
अनावश्यक रूप से संकीर्ण सकता b
विभाजन से पहले। केवल बहुत बड़ी सरणियों के साथ एक मुद्दा। फिर भी एक दिलचस्प मैक्रो।
जैसा कि यह "एम्बेडेड" टैग है, मुझे लगता है कि आप एक माइक्रोकंट्रोलर का उपयोग कर रहे हैं। उपरोक्त सभी सुझाव मान्य हैं और कार्य (रीड-मॉडिफाई-राइट, यूनियन्स, स्ट्रक्चर्स, आदि) हैं।
हालाँकि, आस्टसीलस्कप आधारित डिबगिंग की एक लड़ाई के दौरान मैं यह जानकर चकित रह गया कि इन विधियों में माइक्रो साइकिल के PORTnSET / PORTnCLEAR रजिस्टरों पर सीधे मूल्य लिखने की तुलना में सीपीयू चक्रों में काफी ओवरहेड होता है जो एक वास्तविक अंतर बनाता है जहां तंग छोरों / उच्च होते हैं - ISR की टॉगल पिन।
उन अपरिचितों के लिए: मेरे उदाहरण में, माइक्रो में एक सामान्य पिन-स्टेट रजिस्टर PORTn है जो आउटपुट पिन को दर्शाता है, इसलिए PORTn कर रहा है; = BIT_TO_SET परिणाम को उस रजिस्टर पर रीड-मॉडिफाई-राइट में लिखते हैं। हालाँकि, PORTnSET / PORTnCLEAR रजिस्टर '1' का अर्थ "कृपया इस बिट 1 को बनाएं" (SET) या "कृपया इस बिट को शून्य बनाएं" (CLEAR) और '0' का अर्थ है "पिन को अकेले छोड़ दें"। इसलिए, आप दो पोर्ट एड्रेस के साथ समाप्त होते हैं, इस आधार पर कि आप बिट (हमेशा सुविधाजनक नहीं) सेट या क्लियरिंग कर रहे हैं, लेकिन बहुत तेज़ प्रतिक्रिया और छोटे असेंबल कोड।
volatile
और इसलिए कंपाइलर ऐसे रजिस्टरों को शामिल करने वाले कोड पर कोई अनुकूलन करने में असमर्थ है। इसलिए, इस तरह के कोड को अलग करना अच्छा है और देखें कि यह कोडांतरक स्तर पर कैसे निकला।
बिटफील्ड दृष्टिकोण एम्बेडेड क्षेत्र में अन्य फायदे हैं। आप एक संरचना को परिभाषित कर सकते हैं जो एक विशेष हार्डवेयर रजिस्टर में बिट्स पर सीधे मैप करता है।
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;
आपको बिट पैकिंग ऑर्डर के बारे में पता होना चाहिए - मुझे लगता है कि यह पहले MSB है, लेकिन यह कार्यान्वयन-निर्भर हो सकता है। यह भी सत्यापित करें कि बाइट की सीमाओं को पार करते हुए आपके संकलक फ़ील्ड कैसे बनाते हैं।
फिर आप पहले की तरह व्यक्तिगत मूल्यों को पढ़ सकते हैं, लिख सकते हैं, परीक्षण कर सकते हैं।
#define bit_test(x, y) ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )
नमूना उपयोग:
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;
}
नोट्स: यह तेजी से (इसकी लचीलेपन को देखते हुए) और गैर-शाखा में बनाया गया है। सन स्टूडियो 8 को संकलित करने पर यह कुशल स्पार्क मशीन कोड में परिणत होता है; मैंने amd64 पर MSVC ++ 2008 का उपयोग करके इसका परीक्षण भी किया है। बिट्स की स्थापना और समाशोधन के लिए समान मैक्रो बनाना संभव है। यहाँ कई अन्य लोगों के साथ तुलना में इस समाधान का मुख्य अंतर यह है कि यह किसी भी स्थान पर किसी भी प्रकार के चर के लिए काम करता है।
अधिक सामान्य, मनमाने आकार के बिटमैप के लिए:
#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)))
CHAR_BIT
पहले से परिभाषित है limits.h
, आपको अपने आप में डालने की आवश्यकता नहीं है BITS
(और वास्तव में ऐसा करने से आप अपना कोड ख़राब कर सकते हैं)
यह प्रोग्राम किसी भी डेटा बिट को 0 से 1 या 1 से 0 में बदलने के लिए है:
{
unsigned int data = 0x000000F0;
int bitpos = 4;
int bitvalue = 1;
unsigned int bit = data;
bit = (bit>>bitpos)&0x00000001;
int invbitvalue = 0x00000001&(~bitvalue);
printf("%x\n",bit);
if (bitvalue == 0)
{
if (bit == 0)
printf("%x\n", data);
else
{
data = (data^(invbitvalue<<bitpos));
printf("%x\n", data);
}
}
else
{
if (bit == 1)
printf("elseif %x\n", data);
else
{
data = (data|(bitvalue<<bitpos));
printf("else %x\n", data);
}
}
}
यदि आप बहुत अधिक ट्विडलिंग कर रहे हैं तो आप मास्क का उपयोग करना चाह सकते हैं जो कि पूरी चीज को तेज कर देगा। निम्नलिखित कार्य बहुत तेज हैं और अभी भी लचीले हैं (वे किसी भी आकार के बिट मैप्स में बिट ट्विडलिंग की अनुमति देते हैं)।
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;
}
ध्यान दें, 16 बिट पूर्णांक में 'n' सेट करने के लिए आप निम्नलिखित कार्य करते हैं:
TSetBit( n, &my_int);
यह सुनिश्चित करना आपके ऊपर है कि बिट नंबर आपके द्वारा पास किए जाने वाले बिट मैप की सीमा के भीतर है। ध्यान दें कि बाइट्स, शब्द, पासवर्ड, पासवर्ड आदि छोटे एंडियन प्रोसेसर के लिए, स्मृति में एक दूसरे के लिए सही ढंग से मैप करते हैं (मुख्य कारण यह है कि छोटे एंडियन प्रोसेसर बड़े-एंडियन प्रोसेसर की तुलना में 'बेहतर' हैं, आह, मुझे एक लौ युद्ध लगता है) पर...)।
इसे इस्तेमाल करो:
int ToggleNthBit ( unsigned char n, int num )
{
if(num & (1 << n))
num &= ~(1 << n);
else
num |= (1 << n);
return num;
}
bitset
उत्तर पर विस्तार :
#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;
}
यदि आप लिनक्स कर्नेल में सी प्रोग्रामिंग के साथ यह सब ऑपरेशन करना चाहते हैं तो मैं लिनक्स कर्नेल के मानक एपीआई का उपयोग करने का सुझाव देता हूं।
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
नोट: यहां पूरा ऑपरेशन एक ही चरण में होता है। इसलिए इन सभी को एसएमपी कंप्यूटरों पर भी परमाणु होने की गारंटी दी जाती है और प्रोसेसर के बीच तालमेल बनाए रखने के लिए उपयोगी है।
दृश्य C 2010, और शायद कई अन्य संकलक, में निर्मित बूलियन संचालन के लिए प्रत्यक्ष समर्थन है। एक बूलियन की तरह, बिट में दो संभावित मान हैं, इसलिए हम बूलियन का उपयोग कर सकते हैं - भले ही वे एक बिट से अधिक स्थान लेते हों। इस प्रतिनिधित्व में स्मृति। यह काम करता है, यहां तक कि sizeof()
ऑपरेटर ठीक से काम करता है।
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);
}
तो, अपने प्रश्न के लिए IsGph[i] =1
, या IsGph[i] =0
सेटिंग आसान और क्लीयरिंग बूल आसान बनाते हैं।
अनपेक्षित वर्ण खोजने के लिए:
// 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;
}
}
ध्यान दें कि इस कोड के बारे में "विशेष" कुछ भी नहीं है। यह एक पूर्णांक की तरह थोड़ा व्यवहार करता है - जो तकनीकी रूप से, यह है। एक 1 बिट पूर्णांक जो 2 मान और 2 मान रख सकता है।
मैंने एक बार डुप्लिकेट लोन रिकॉर्ड खोजने के लिए इस दृष्टिकोण का उपयोग किया था, जहां ऋण_नंबर आईएसएएम कुंजी था, 6-अंकीय ऋण संख्या को बिट सरणी में सूचकांक के रूप में उपयोग करता है। बहुत तेजी से, और 8 महीनों के बाद, यह साबित हुआ कि हम जिस मेनफ्रेम प्रणाली से डेटा प्राप्त कर रहे थे वह वास्तव में खराबी थी। बिट सरणियों की सादगी उनके शुद्धता में बहुत अधिक विश्वास करती है - उदाहरण के लिए एक खोज दृष्टिकोण बनाम।
bool
। C89 सेटअप के लिए हो सकता है कि यहां तक कि 4 बाइट का उपयोग int
लागू करने के लिएbool
यहाँ कुछ मैक्रोज़ हैं जिनका मैं उपयोग करता हूँ:
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)
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);
}
check_nth_bit
हो सकता है bool
।
मान लीजिए कि कुछ चीजें पहले
num = 55
इंटेगर ने बिटवाइज ऑपरेशन (सेट, प्राप्त, स्पष्ट, टॉगल) करने के लिए की हैं।
n = 4
बिटवाइज़ ऑपरेशन करने के लिए 0 आधारित बिट स्थिति।
nth
संख्या सही बदलाव के बिट num
, n
बार। फिर बिटवाइज़ और &
1 के साथ प्रदर्शन करें ।bit = (num >> n) & 1;
यह काम किस प्रकार करता है?
0011 0111 (55 in decimal)
>> 4 (right shift 4 times)
-----------------
0000 0011
& 0000 0001 (1 in decimal)
-----------------
=> 0000 0001 (final result)
n
बार। फिर बिटवाइज़ या |
ऑपरेशन करें num
।num |= (1 << n); // Equivalent to; num = (1 << n) | num;
यह काम किस प्रकार करता है?
0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
0001 0000
| 0011 0111 (55 in decimal)
-----------------
=> 0001 0000 (final result)
n
बार यानी 1 << n
।~ (1 << n)
।&
उपरोक्त परिणाम के साथ बिटवाइज़ और ऑपरेशन करें और num
। उपरोक्त तीन चरणों को एक साथ लिखा जा सकता है num & (~ (1 << n))
;num &= (~(1 << n)); // Equivalent to; num = num & (~(1 << n));
यह काम किस प्रकार करता है?
0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
~ 0001 0000
-----------------
1110 1111
& 0011 0111 (55 in decimal)
-----------------
=> 0010 0111 (final result)
बिट को टॉगल करने के लिए हम बिट वाइज XOR ^
ऑपरेटर का उपयोग करते हैं । बिटवाइंड XOR ऑपरेटर 1 का मूल्यांकन करता है, यदि दोनों ऑपरेंड के संबंधित बिट अलग-अलग हैं, अन्यथा 0 का मूल्यांकन करता है।
जिसका अर्थ है कि थोड़ा सा टॉगल करें, हमें उस XOR ऑपरेशन को करने की आवश्यकता है जिसमें आप टॉगल करना चाहते हैं और 1।
num ^= (1 << n); // Equivalent to; num = num ^ (1 << n);
यह काम किस प्रकार करता है?
0 ^ 1 => 1
। 1 ^ 1 => 0
। 0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
0001 0000
^ 0011 0111 (55 in decimal)
-----------------
=> 0010 0111 (final result)
अनुशंसित पढ़ने - बिटवाइज ऑपरेटर अभ्यास
आप एकल बिट को कैसे सेट, स्पष्ट और टॉगल करते हैं?
मास्क बनाने का प्रयास करते समय एक आम कोडिंग पिटफॉल को संबोधित करने के लिए:
1
हमेशा पर्याप्त चौड़ा नहीं होता है
number
व्यापक प्रकार की तुलना में क्या समस्याएं होती हैं 1
? अपरिभाषित व्यवहार (UB) के लिए अग्रणी
x
पारी के लिए बहुत अच्छा हो सकता है । यहां तक कि अगर बहुत महान नहीं है, तो पर्याप्त रूप से सबसे महत्वपूर्ण बिट्स फ्लिप नहीं कर सकते हैं।1 << x
x
~
// 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 पर्याप्त चौड़ा है:
कोड का उपयोग 1ull
कर सकते हैं या pedantically (uintmax_t)1
और संकलक अनुकूलन करते हैं।
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
या कास्ट - जो कलाकारों को सही और अप-टू-डेट रखने के लिए कोडिंग / समीक्षा / रखरखाव मुद्दों के लिए बनाता है।
number |= (type_of_number)1 << x;
या धीरे से 1
एक गणित ऑपरेशन को मजबूर करके बढ़ावा दें जो कि कम से कम के प्रकार के रूप में व्यापक है number
।
number |= (number*0 + 1) << x;
सबसे बिट जोड़तोड़ के साथ, हस्ताक्षरित लोगों के बजाय अहस्ताक्षरित प्रकारों के साथ काम करने के लिए सबसे अच्छा है
number |= (type_of_number)1 << x;
और न ही number |= (number*0 + 1) << x;
... तथ्य के रूप में, न ही है number |= (1ull << x);
। क्या स्थिति के अनुसार इसे करने का एक पोर्टेबल तरीका है?
C ++ 11 टेम्प्लेटेड संस्करण (हेडर में रखा गया):
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;}
}
;
अपने कार्य की परिभाषा के बाद क्यों है ?)
(variable & bits == bits)
?
((variable & bits) == bits)
std::bitset
c ++ 11 में उपयोग करें
यह कार्यक्रम @ जेरेमी के उपरोक्त समाधान से बाहर है। यदि कोई जल्दी से चारों ओर खेलना चाहता है।
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
सी भाषा में इन कार्यों में से एक को n थोड़ा बदलने की कोशिश करें:
char bitfield;
// Start at 0th position
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}
या
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}
या
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 << n
अपरिभाषित व्यवहार का कारण हो सकता है