2008-09-15 15 views
7

मैं अपने डेटा संपीड़न विचार को लागू करने की कोशिश कर रहा हूं, और चूंकि मैं परीक्षण डेटा के बड़े कॉर्पस के खिलाफ इसे चलाने की कल्पना कर रहा हूं, इसलिए मैंने इसे सी में कोड करने के लिए सोचा था (मुझे ज्यादातर स्क्रिप्टिंग भाषाओं जैसे अनुभव रूबी और टीसीएल।)बिटवाई इंडेक्सिंग?

सी पर O'Reilly 'गाय' किताबों के माध्यम से देखकर, मुझे एहसास हुआ कि मैं बस एक साधारण 'चार' या 'int' प्रकार चर के बिट्स को इंडेक्स नहीं कर सकता जैसा मैं चाहूंगा bitwise तुलना और ऑपरेटरों करने के लिए।

क्या मैं इस धारणा में सही हूं? क्या मेरे लिए एक बिट प्रकार का प्रतिनिधित्व करने के लिए एक समेकित प्रकार का उपयोग करना उचित है (और इनमें से एक सरणी बनाना, और चार से कनवर्ट करने के लिए फ़ंक्शन लिखना)? यदि हां, तो क्या ऐसा कोई प्रकार और फ़ंक्शंस मानक पुस्तकालय में पहले से कहीं परिभाषित है? क्या अन्य (बेहतर?) दृष्टिकोण हैं? क्या वहां कुछ उदाहरण कोड है कि कोई मुझे इंगित कर सकता है?

धन्यवाद -

उत्तर

10

काइल ने जो कहा है उसके बाद, आप अपने लिए कड़ी मेहनत करने के लिए एक मैक्रो का उपयोग कर सकते हैं।

यह संभव है।

वें बिट, उपयोग सेट करने के लिए या:

x | = (1 < < 5); // 6 वीं से सही

थोड़ा, उपयोग साफ करने के लिए और सेट:

एक्स & = ~ (1 < < 5); // को साफ करता है 6-से-सही

थोड़ा, उपयोग XOR फ्लिप करने के लिए:

x^= (1 < < 5); // flips 6-से-सही

या ...

#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true/false if bit is set 
#define SetBit(var, bit) (var |= (1 << bit)) 
#define FlipBit(var, bit) (var ^= (1 << bit)) 

तो फिर तुम इसे पसंद कोड में उपयोग कर सकते हैं:

int myVar = 0; 
SetBit(myVar, 5); 
if (GetBit(myVar, 5)) 
{ 
    // Do something 
} 
+0

यह बहुत उपयोगी है, बहुत बहुत धन्यवाद। –

7

यह संभव है।

वें बिट, उपयोग सेट करने के लिए या:

x |= (1 << 5); // sets the 5th-from right 

थोड़ा, उपयोग साफ करने के लिए और:

x ^= (1 << 5); // flips 5th-from-right 

:

x &= ~(1 << 5); // clears 5th-from-right 

थोड़ा, उपयोग XOR से घुमाने के लिए थोड़ा उपयोग शिफ्ट का मूल्य प्राप्त करने के लिए और AND:

(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right 

नोट: शिफ्ट दाएं 5 यह सुनिश्चित करना है कि मान 0 या 1 है। यदि आप 0/0 0 में रुचि रखते हैं, तो आप शिफ्ट के बिना प्राप्त कर सकते हैं।

0

आप सूचकांक करने के लिए एक सा आप कर सकते थे चाहते हैं:

bit = (char & 0xF0) >> 7; 

एक चार की MSB हो जाता है। आप सही शिफ्ट छोड़ सकते हैं और 0.

bit = char & 0xF0; 

यदि बिट सेट परिणाम सेट किया गया है तो 0 पर होगा।

स्पष्ट रूप से, आपको विभिन्न बिट्स प्राप्त करने के लिए मास्क को बदलने की आवश्यकता है (एनबी: 0xF थोड़ा मुखौटा है अगर यह अस्पष्ट है)। कई मास्क को परिभाषित करना संभव है उदा।

#define BIT_0 0x1 // or 1 << 0 
#define BIT_1 0x2 // or 1 << 1 
#define BIT_2 0x4 // or 1 << 2 
#define BIT_3 0x8 // or 1 << 3 

आदि ...

यह आपको देता है:

bit = char & BIT_1; 

आप या तो एक मैक्रो या एक समारोह के भीतर सूचकांक थोड़ा सफलतापूर्वक में उपरोक्त कोड में इन परिभाषाओं का उपयोग कर सकते हैं।

एक सा सेट करने के लिए:

char &= ~BIT_3 

थोड़ा

char ^= BIT_4 

इस मदद को चालू करने के लिए:

char |= BIT_2; 

थोड़ा साफ़ करने के लिए?

1

विशिष्ट सूचकांक के साथ बिट के राज्य क्वेरी करने के लिए:

int index_state = variable & (1 << bit_index); 

सेट करने के लिए बिट:

varabile |= 1 << bit_index; 

पुनरारंभ करने के लिए बिट:

variable &= ~(1 << bit_index); 
0

बिट्स के लिए एक मानक पुस्तकालय कंटेनर नहीं है : std :: वेक्टर। यह लाइब्रेरी में अंतरिक्ष कुशल होने के लिए विशिष्ट है। एक गतिशील_बिसेट कक्षा भी है।

ये आपको अंतर्निहित भंडारण के एक बिट प्रति मान का उपयोग करके बुलियन मूल्यों के सेट पर संचालन करने देगा।

Boost dynamic bitset documentation

एसटीएल दस्तावेज़ीकरण के लिए, अपने संकलक दस्तावेज़ देखें।

बेशक, आप हाथ से अन्य अभिन्न प्रकारों में व्यक्तिगत बिट्स को भी संबोधित कर सकते हैं। यदि आप ऐसा करते हैं, तो आपको असाइन किए गए प्रकारों का उपयोग करना चाहिए ताकि उच्च बिट सेट वाले मान पर सही बदलाव करने का निर्णय लेने पर आपको अपरिभाषित व्यवहार न हो। हालांकि, ऐसा लगता है जैसे आप कंटेनर चाहते हैं।

टिप्पणी करने वाले टिप्पणीकर्ता के लिए 32x अधिक जगह लेनी आवश्यक है: boost :: dynamic_bitset और वेक्टर प्रति बिट एक बिट का उपयोग करने के लिए विशिष्ट हैं, और इसलिए कोई स्पेस पेनल्टी नहीं है, यह मानते हुए कि आप वास्तव में संख्या से अधिक चाहते हैं एक प्राचीन प्रकार में बिट्स का। ये कक्षाएं आपको कुशल अंतर्निहित भंडारण वाले बड़े कंटेनर में अलग-अलग बिट्स को संबोधित करने की अनुमति देती हैं। यदि आप बस 32 बिट्स चाहते हैं (कहें), हर तरह से, एक int का उपयोग करें। यदि आप कुछ बड़ी संख्या में बिट्स चाहते हैं, तो आप लाइब्रेरी कंटेनर का उपयोग कर सकते हैं।

+0

यह आवश्यकतानुसार 32x अधिक डेटा का उपयोग करता है। मूल पोस्टर ने कहा कि वह डेटा संपीड़न में रुचि रखते थे। यह विपरीत की तरह लगता है! –

+0

नहीं, वेक्टर के बारे में बिंदु और boost :: dynamic_bitset यह है कि वे एक बिट प्रति बूल का उपयोग करते हैं। 1024 बूल स्टोर करने के लिए, वे 128 बाइट्स और क्लास ओवरहेड का उपयोग करेंगे। आप आवश्यक से 32x अधिक भंडारण की गणना कैसे की? – janm

2

थ्योरी

वहाँ तक पहुँचने या एक अंतर्निहित डेटाप्रकार (उदाहरण के लिए 'चार') के एन-वें बिट स्थापित करने के लिए कोई सी वाक्य रचना है। हालांकि, आप लॉजिकल और ऑपरेशन का उपयोग करके बिट्स तक पहुंच सकते हैं, और लॉजिकल या ऑपरेशन का उपयोग करके बिट्स सेट कर सकते हैं।

उदाहरण के तौर पर, कहें कि आपके पास एक चर है जिसमें 1101 है और आप बाईं ओर से दूसरी बिट देखना चाहते हैं।बस एक तार्किक और प्रदर्शन 0100 के साथ:

1101 
0100 
---- AND 
0100 

परिणाम गैर शून्य है, तो 2 बिट चाहिए निर्धारित किया गया है है; अन्यथा सेट नहीं किया गया था।

आप बाएं से 3 बिट सेट करने के लिए चाहते हैं, तो एक तार्किक या 0010 के साथ प्रदर्शन:

1101 
0010 
---- OR 
1111 

आप और सी ऑपरेटरों का उपयोग कर सकते & & (के लिए और) || (OR के लिए) इन कार्यों को करने के लिए। आपको अपने आप को बिट एक्सेस पैटर्न (उपरोक्त उदाहरणों में 0100 और 0010) बनाने की आवश्यकता होगी। यह चाल याद रखना है कि कम से कम महत्वपूर्ण बिट (एलएसबी) 1 एस की गणना करता है, अगली एलएसबी 2 एस, फिर 4 एस आदि की गणना करता है। इसलिए, एन-वें एलएसबी (0 से शुरू होने) के लिए बिट एक्सेस पैटर्न केवल 2^एन। सी में गणना करने का सबसे आसान तरीका बाइनरी वैल्यू 0001 (इस चार बिट उदाहरण में) को आवश्यक संख्याओं के बायीं तरफ स्थानांतरित करना है। इस मान को हमेशा अहस्ताक्षरित पूर्णांक की तरह मात्रा में 1 के बराबर है के रूप में, यह सिर्फ उदाहरण

unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */ 

/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */ 
unsigned char pattern = 1; 
pattern <<= 3; /* Shift pattern left by three places.*/ 

if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */ 

/* Set the most significant bit. */ 
myVal |= (char)(1<<7); 

यह उदाहरण परीक्षण नहीं किया गया है '1 < < एन'

, लेकिन करने के लिए काम करना चाहिए सामान्य विचार को चित्रित करें।

1

व्यक्तिगत बिट्स के रूप में निम्नानुसार सूचीबद्ध किए जा सकते ।

इस तरह का struct को परिभाषित करें:

CopyMemory(&input, &value, sizeof(value)); 

अगर देखने के लिए:

struct 
{ 
    unsigned bit0  : 1; 
    unsigned bit1  : 1; 
    unsigned bit2  : 1; 
    unsigned bit3  : 1; 
    unsigned reserved : 28; 
} bitPattern; 

अब अगर मैं "मूल्य" नाम के एक वर के अलग-अलग बिट मूल्यों जानना चाहते हैं, तो निम्न करें बिट 2 उच्च या निम्न है:

int state = bitPattern.bit2; 

आशा है कि इससे मदद मिलती है।

संबंधित मुद्दे