दिलचस्प पोस्ट
इकाई फ़्रेमवर्क मॉडल परिभाषाओं में वर्ग गुणों के लिए 'आभासी' का उपयोग क्यों करें? php मैं कैसे एक बाहरी प्रोग्राम चल रहा है – सिस्टम और exec के साथ परेशानी हो रही है जॉन स्कीट स्पष्टीकरण द्वारा सिंगलटन ClearCase में, मैं एक फ़ाइल के पुराने संस्करण को एक स्थिर दृश्य में कैसे देख सकता हूँ, कमांड लाइन से? फिक्स चेतावनी "विवरण के लिए सी-स्टाइल नापसंद है" स्विफ्ट 3 में जावास्क्रिप्ट का उपयोग करके ब्राउजर बैक बटन को कैसे रोकें Android में ब्लूटूथ सॉकेट डिस्कनेक्ट करें क्यों अजगर dict.update () ऑब्जेक्ट वापस नहीं? socket.io.js नहीं मिला घोषित करने वाले संकेतक; प्रकार और नाम के बीच अंतरिक्ष के बाईं या दाईं तरफ तारांकन? तत्वों में पॉलिमर साझा शैलियों कुछ सीपीयू पर तंग छोरों में एडीसी / एसबीबी और आईएनसी / डीईसी के साथ समस्याएं ओरेकल में जुड़ें क्वेरी के साथ अपडेट करें एमएस एक्सेस क्वेरी: एक क्वेरी के माध्यम से पंक्तियाँ जोड़ना कस्टम फेसबुक लॉगिन बटन – एंड्रॉइड

सी / सी ++ में मनमानी बिट्स को कैसे पढ़ा / लिखना

मान लें कि मेरे पास 11111111 के द्विआधारी मूल्य के साथ एक बाइट बी है

मैं उदाहरण के लिए कैसे दूसरे बिट पर शुरू होने वाला एक 3 बिट पूर्णांक मान पढ़ सकता हूं या पांचवीं बिट से शुरू होने वाला चार बिट पूर्णांक मान लिख सकता हूँ?

वेब के समाधान से एकत्रित समाधान "सी / सी ++ में मनमानी बिट्स को कैसे पढ़ा / लिखना"

इस प्रश्न के बारे में पूछे जाने के कुछ 2 साल बाद मैं इसे जिस तरह से समझाना चाहता हूं, इसे स्पष्ट करना चाहता हूं, जब मैं अभी भी एक नया एनबीबी था और जो लोग इस प्रक्रिया को समझना चाहते हैं, उनके लिए सबसे फायदेमंद होगा।

सबसे पहले, "11111111" उदाहरण मान भूल जाते हैं, जो वास्तव में प्रक्रिया के दृश्य विवरण के लिए उपयुक्त नहीं हैं। तो प्रारंभिक मान 10111011 (187 दशमलव) हो, जो कि प्रक्रिया के थोड़ा और अधिक उदाहरण होगा।

1 – दूसरे बिट से शुरू होने वाला 3 बिट मूल्य कैसे पढ़ा जाए:

  ___ <- those 3 bits 10111011 

मान 101 है, या दशमलव में 5, इसे पाने के 2 संभावित तरीके हैं:

  • मुखौटा और बदलाव

इस दृष्टिकोण में, आवश्यक बिट्स पहले मूल्य 00001110 (14 दशमलव) के साथ 00001110 बाद इसे स्थानांतरित कर दिया गया है:

  ___ 10111011 AND 00001110 = 00001010 >> 1 = ___ 00000101 

इसके लिए अभिव्यक्ति होगी: (value & 14) >> 1

  • शिफ्ट और मास्क

यह दृष्टिकोण समान है, लेकिन परिचालन का क्रम उलट है, जिसका अर्थ है कि मूल मान स्थानांतरित हो गया है और फिर 00000111 (7) के साथ मुखौटे केवल पिछले 3 बिट्स को छोड़ दें:

  ___ 10111011 >> 1 ___ 01011101 AND 00000111 00000101 

इसके लिए अभिव्यक्ति होगी: (value >> 1) & 7

दोनों तरीकों में जटिलता की समान मात्रा शामिल है, और इसलिए प्रदर्शन में भिन्न नहीं होगी।

2 – दूसरा बिट से शुरू होने वाला 3 बिट मान कैसे लिखना है:

इस मामले में, प्रारंभिक मूल्य ज्ञात है, और जब कोड में यह मामला है, तो आप ज्ञात मूल्य को दूसरे ज्ञात मूल्य के रूप में सेट करने में सक्षम हो सकते हैं जो कम परिचालन का उपयोग करता है, लेकिन वास्तव में यह शायद ही कभी मामला, ज्यादातर समय कोड को प्रारंभिक मान न तो पता चल जाएगा, न ही वह लिखा जाना चाहिए।

इसका मतलब है कि नए मान को बाइट में सफलतापूर्वक "स्प्लिचर्ड" करने के लिए, लक्ष्य बिट्स को शून्य पर सेट किया जाना चाहिए, जिसके बाद स्थानांतरित किया गया स्थान "स्प्लिचर्ड" होगा, जो पहला कदम है:

  ___ 10111011 AND 11110001 (241) = 10110001 (masked original value) 

दूसरा चरण है कि हम 3 बिट्स में लिखना चाहते हैं उस बदलाव को बदलना है, हम कहते हैं कि 101 (5) से 110 (6)

  ___ 00000110 << 1 = ___ 00001100 (shifted "splice" value) 

तीसरे और अंतिम चरण को स्थानांतरित "ब्याह" मान के साथ मुखौटे वाले मूल मूल्य को बांधा देना है:

 10110001 OR 00001100 = ___ 10111101 

पूरी प्रक्रिया के लिए अभिव्यक्ति होगी: (value & 241) | (6 << 1) (value & 241) | (6 << 1)

बोनस – मास्क पढ़ने और लिखने के तरीके:

स्वाभाविक रूप से, दशमलव कनवर्टर के लिए द्विआधारी का इस्तेमाल करना सुरुचिपूर्ण से बहुत दूर है, खासकर 32 और 64 बिट कंटेनरों के मामले में – दशमलव मानों को पागल बड़ा हो जाता है। अभिव्यक्ति के साथ मुखौटे आसानी से उत्पन्न करने के लिए संभव है, जो संकलक कुशलतापूर्वक संकलन के दौरान हल कर सकता है:

  • "मुखौटा और बदलाव" के लिए मुखौटा पढ़ें: ((1 << fieldLength) - 1) << (fieldIndex - 1) , यह मानते हुए कि पहले बिट पर अनुक्रमणिका 1 (शून्य नहीं)
  • "पाली और मुखौटा" के लिए मुखौटा पढ़ें: (1 << fieldLength) - 1 (सूचकांक यहां एक भूमिका नहीं निभाता है क्योंकि यह हमेशा पहले बिट में स्थानांतरित होता है
  • लिखने मुखौटा: ~ ऑपरेटर के साथ "मुखौटा और शिफ्ट" मुखौटा अभिव्यक्ति को उलट कर दें

यह कैसे काम करता है (उपरोक्त उदाहरणों से दूसरी बिट से शुरू होने वाली 3bit फ़ील्ड के साथ)?

 00000001 << 3 00001000 - 1 00000111 << 1 00001110 ~ (read mask) 11110001 (write mask) 

वही उदाहरण व्यापक पूर्णांक और मनमानी बिट चौड़ाई और क्षेत्र की स्थिति पर लागू होते हैं, तदनुसार शिफ्ट और मुखौटा मूल्यों के अनुसार भिन्न होते हैं।

यह भी ध्यान रखें कि उदाहरण अहस्ताक्षरित पूर्णांक को ग्रहण करते हैं, जो कि आप पूर्णांकों को पोर्टेबल बिट-फील्ड विकल्प के रूप में उपयोग करने के लिए उपयोग करना चाहते हैं (नियमित बिट-फ़ील्ड पोर्टेबल होने के लिए मानक द्वारा गारंटीकृत किसी भी तरह से नहीं हैं), दोनों बाएं और दाएं बदलाव एक पैडिंग 0 डालें, जो कि एक हस्ताक्षरित पूर्णांक को सही स्थानांतरित करने का मामला नहीं है।

यहां तक ​​कि आसान:

मैक्रोज़ के इस सेट का उपयोग करना (लेकिन केवल सी ++ में क्योंकि यह सदस्य कार्यों की पीढ़ी पर निर्भर है):

 #define GETMASK(index, size) (((1 << (size)) - 1) << (index)) #define READFROM(data, index, size) (((data) & GETMASK((index), (size))) >> (index)) #define WRITETO(data, index, size, value) ((data) = ((data) & (~GETMASK((index), (size)))) | ((value) << (index))) #define FIELD(data, name, index, size) \ inline decltype(data) name() { return READFROM(data, index, size); } \ inline void set_##name(decltype(data) value) { WRITETO(data, index, size, value); } 

आप कुछ के लिए सरल रूप में जा सकते हैं:

 struct A { uint bitData; FIELD(bitData, one, 0, 1) FIELD(bitData, two, 1, 2) }; 

और यहां तक ​​कि बिट फ़ील्ड को गुणों के रूप में लागू किया जा सकता है जो आप आसानी से एक्सेस कर सकते हैं:

 A a; a.set_two(3); cout << a.two(); 

जीसीसी के decltype -प्री-सी ++ 11 के साथ decltype बदलें

आपको मूल्य बदलने और मुखौटा करने की आवश्यकता है, उदाहरण के लिए …

यदि आप पहले दो बिट्स को पढ़ना चाहते हैं, तो आपको उन्हें ऐसा बंद करने की आवश्यकता है:

 int value = input & 0x3; 

यदि आप इसे ऑफसेट करना चाहते हैं तो आपको सही एन बिट्स को स्थानांतरित करने की आवश्यकता है और फिर आप चाहते हैं कि बिट्स को बंद करें:

 int value = (intput >> 1) & 0x3; 

आपके जैसे तीन बिट्स को पढ़ने के लिए अपने प्रश्न में पूछा।

 int value = (input >> 1) & 0x7; 

आपको एक बदलाव और मुखौटा (और) संचालन करना होगा। चलो किसी भी बाइट हो और पी उस सूचक का (> = 0) हो, जिसमें से आप n बिट्स (> = 1) लेना चाहते हैं।

सबसे पहले आपको पी बार से सही बी बदलना होगा:

 x = b >> p; 

दूसरा आपको एन के साथ परिणाम मास्क करना होगा:

 mask = (1 << n) - 1; y = x & mask; 

आप मैक्रो में सब कुछ डाल सकते हैं:

 #define TAKE_N_BITS_FROM(b, p, n) ((b) >> (p)) & ((1 << (n)) - 1) 

"मैं उदाहरण के लिए दूसरा बिट पर शुरू होने वाला एक 3 बिट पूर्णांक मान कैसे पढ़ूं?"

 int number = // whatever; uint8_t val; // uint8_t is the smallest data type capable of holding 3 bits val = (number & (1 << 2 | 1 << 3 | 1 << 4)) >> 2; 

(मुझे लगता है कि "दूसरा बिट" बिट # 2 है, जो कि वास्तव में तीसरा बिट है।)

बाइट्स पढ़ने के लिए std :: bitset का उपयोग करें

 const int bits_in_byte = 8; char myChar = 's'; cout << bitset<sizeof(myChar) * bits_in_byte>(myChar); 

लिखने के लिए आपको बिट-वार ऑपरेटर जैसे & ^ | & << >> यह जानने के लिए सुनिश्चित करें कि वे क्या करते हैं

उदाहरण के लिए 00100100 के लिए आपको पहले बिट को 1 में सेट करना होगा, और इसे << >> ऑपरेटर के साथ 5 गुना करना होगा। अगर आप लिखना जारी रखना चाहते हैं तो आप पहले बिट को सेट करते हैं और इसे बदलते रहें यह बहुत पुराने टाइपराइटर की तरह है: आप लिखते हैं, और पेपर को बदलते हैं।

00100100 के लिए: पहले बिट को 1 पर सेट करें, 5 गुना बदलाव करें, पहले बिट को 1 में सेट करें, और 2 बार पाल करें:

 const int bits_in_byte = 8; char myChar = 0; myChar = myChar | (0x1 << 5 | 0x1 << 2); cout << bitset<sizeof(myChar) * bits_in_byte>(myChar); 

बस इस और feelfree का उपयोग करें:

 #define BitVal(data,y) ( (data>>y) & 1) /** Return Data.Y value **/ #define SetBit(data,y) data |= (1 << y) /** Set Data.Y to 1 **/ #define ClearBit(data,y) data &= ~(1 << y) /** Clear Data.Y to 0 **/ #define TogleBit(data,y) (data ^=BitVal(y)) /** Togle Data.Y value **/ #define Togle(data) (data =~data ) /** Togle Data value **/ 

उदाहरण के लिए:

 uint8_t number = 0x05; //0b00000101 uint8_t bit_2 = BitVal(number,2); // bit_2 = 1 uint8_t bit_1 = BitVal(number,1); // bit_1 = 0 SetBit(number,1); // number = 0x07 => 0b00000111 ClearBit(number,2); // number =0x03 => 0b0000011 
 int x = 0xFF; //your number - 11111111 

मैं उदाहरण के लिए दूसरे बिट पर शुरू होने वाली एक 3 बिट पूर्णांक मान कैसे पढ़ूं?

 int y = x & ( 0x7 << 2 ) // 0x7 is 111 // and you shift it 2 to the left 

यदि आप अपने डेटा से बिट्स हथियाने रखते हैं, तो आप थोड़ी-फ़िली का उपयोग करना चाह सकते हैं। आपको सिर्फ एक स्ट्रेट सेट अप करना होगा और इसे केवल लोगों और शून्य के साथ लोड करना होगा:

 struct bitfield{ unsigned int bit : 1 } struct bitfield *bitstream; 

तो बाद में इसे इस तरह लोड करें (int या जो डेटा आप लोड कर रहे हैं के साथ चार जगह):

 long int i; int j, k; unsigned char c, d; bitstream=malloc(sizeof(struct bitfield)*charstreamlength*sizeof(char)); for (i=0; i<charstreamlength; i++){ c=charstream[i]; for(j=0; j < sizeof(char)*8; j++){ d=c; d=d>>(sizeof(char)*8-j-1); d=d<<(sizeof(char)*8-1); k=d; if(k==0){ bitstream[sizeof(char)*8*i + j].bit=0; }else{ bitstream[sizeof(char)*8*i + j].bit=1; } } } 

फिर अभिगम तत्वों:

 bitstream[bitpointer].bit=... 

या

 ...=bitstream[bitpointer].bit 

यह सब सोच रहा है कि I86 / 64 पर काम नहीं कर रहा है, क्योंकि बांह बड़ा या छोटा अंतराल हो सकता है।