2010-08-07 19 views
5

मुझे सी में 0-15 के बीच एक मूल्य स्टोर करने की आवश्यकता है, इसके लिए 4 बिट पर्याप्त हैं। मैं सिर्फ 4 बिट्स का चर कैसे कर सकता हूं? अंतरिक्ष यहां एक बाधा हैमैं सी में बिट जानकारी का प्रतिनिधित्व कैसे करूं?

उत्तर

7

char का उपयोग करने पर विचार करें। हाँ, यह 8-बिट्स है, लेकिन आप अन्य 4 बिट्स में मानों को संग्रहीत करने के लिए बिट शिफ्ट ऑपरेटर (<< और >>) का उपयोग कर सकते हैं।

संपादित करें: नीचे टिप्पणी प्रति, एक unsigned charchar से अधिक बेहतर संकेत बिट के साथ मुद्दों से बचने के लिए वास्तव में, है।

+0

आप बिट 4 ऑपरेटरों का उपयोग 'चार' में दो 4-बिट मानों को स्टोर करने के लिए कर सकते हैं। लेकिन आपको 'हस्ताक्षरित चार' का उपयोग करना सुनिश्चित करना चाहिए या फिर आपको हस्ताक्षरित स्थानांतरण के साथ भद्दा व्यवहार मिलेगा। –

4

आप अपने 4 बिट्स को स्टोर करने के लिए bitfield का उपयोग कर सकते हैं, हालांकि, जब तक कि उनमें से कई उनमें से किसी एक संरचना में न हों, तो आप बाइट में मान को संग्रहीत करने के लिए किसी भी स्थान को सहेज नहीं पाएंगे।

+1

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

+0

इसके अलावा, सशर्त उपयोग किए बिना बिटफील्ड को संबोधित करने का कोई तरीका नहीं है। यदि आप अपने आप को 'हस्ताक्षरित चार' में पैकिंग करते हैं, तो आप बस इंडेक्स के निम्न बिट का उपयोग कर सकते हैं, उदा। '(i और 1) << 2', एक शिफ्ट ऑपरेंड के रूप में। –

0

आधे बाइट के लिए शब्द एक नींबू है। तो यहाँ:

struct two_nibbles { 
    unsigned a :4; 
    unsigned b :4; 
} 

आप अपने दो चर x.a और x.b नाम है (लेकिन जो कुछ भी करने के लिए x बदल) है, लेकिन आप एक छोटे से अंतरिक्ष बचा सकते हैं। आप जांचना चाहेंगे, हालांकि - मुझे लगता है कि संकलक सुनिश्चित करेगा कि sizeof(struct two_nibbles) == sizeof(char) लेकिन ऐसा नहीं हो सकता है, इसलिए आपको अंतरिक्ष के लायक बनाने के लिए और अधिक निबल्स जोड़ना पड़ सकता है।

+0

एक और बी को बिना हस्ताक्षरित के रूप में परिभाषित करके वे स्वचालित रूप से पूर्णांक हो सकते हैं, इसलिए 4+ बाइट्स पर कब्जा कर रहे हैं? – Laz

+0

नहीं - आप क्रिस द्वारा यहां दिखाए गए नोटेशन का उपयोग करके, किसी संरचना में हस्ताक्षरित इनट्स के साथ सटीक निर्दिष्ट कर सकते हैं। ऊपर दिए गए उदाहरण में प्रत्येक फ़ील्ड ए और बी 4 बिट्स का उपयोग करेगा। हालांकि यह याद रखना महत्वपूर्ण है कि संकलक ऐसी संरचना के अंत में पैडिंग जोड़ सकता है। – gnud

+0

कंपाइलर ** ** ** (अभ्यास में) उन्हें 4+ बाइट बना देगा। आपको 'हस्ताक्षरित चार ए: 4 का उपयोग करना चाहिए; हस्ताक्षर किए गए चार बी: 4; 'या बेहतर अभी तक बिटकफील्ड फेंक दें (सी भाषा में सबसे बेवकूफ, सबसे बेकार चीजों में से एक) और थोड़ा अंकगणित करें ताकि आपको अच्छी तरह से परिभाषित व्यवहार मिल सके। गैर-योग्य हैक्स के लिए –

3

आपके पास वास्तव में एक 4-बिट चर नहीं हो सकता है, लेकिन आपके पास 8-बिट चर हो सकते हैं जो दो 4-बिट मानों को संग्रहीत करते हैं, लेकिन आपको उन्हें अस्थायी रूप से एक्सेस करना होगा, जिसका अर्थ है कि आप किसी भी स्थान को सहेजते नहीं हैं जब तक आप दो से अधिक है: unsigned char myOneBitVariable:1; और अपने मामले 'अहस्ताक्षरित चार MyFourBitVariable के लिए:

uint8_t var_both; 
uint8_t temp = (var_both >> 4) & 0x0F; // For first value 
temp = var_both & 0x0F; // For second value 
2

के रूप में क्रिस लुट्ज़ निर्दिष्ट, आप बिट्स कि एक चर एक कॉलन और इसका आकार जोड़कर का उपयोग करता है की राशि निर्धारित कर सकते हैं: 4 '। मैं यह इंगित करना चाहता हूं कि बेहद मुश्किल यह है और क्यों आपको इसे से बचना चाहिए।

अधिकांश आधुनिक कंपाइलर्स आपकी संरचना में आपके चर के लिए स्थान को संरेखित करेंगे। सबसे आम मामला आज 4 बाइट्स या यहां तक ​​कि 8 बाइट्स है, लेकिन यह मंच से मंच और कंपाइलर से कंपाइलर में भिन्न होता है। कुछ कंपाइलर आपको डेटा और उसके सदस्यों के संरेखण को निर्दिष्ट करने की अनुमति देते हैं। जीसीसी पर कीवर्ड __attribute__((aligned(x))) है और एमएसवीसी पर यह __declspec(align(x)) है। ज्यादातर मामलों में आपको यह भी निर्दिष्ट करना होगा कि कंपाइलर को संरचनाओं को कितना पैक करना चाहिए। एमएसवीसी में #pragma pack(x) निर्देश है: http://msdn.microsoft.com/en-us/library/2e70t5y1(VS.80).aspx। आप यहां एमएसवीसी संरेखण के बारे में भी पढ़ सकते हैं: http://msdn.microsoft.com/en-us/library/83ythb65(VS.80).aspx। जीसीसी का अपना कार्यान्वयन __attribute__ ((__packed__) है, जिसे आपको आसपास खोजना पड़ सकता है। एक उदाहरण है कि आप नहीं दे करता है कि आप क्या चाहते, माइक्रोसॉफ्ट के संकलक का उपयोग कर:


#ifndef _MSC_VER 
#error This alignment solution/packing solution is only valid on MSC 
#endif /* ifndef _MSC_VER */ 

#define M_ALIGN(x) __declspec(align(x)) 

struct S64Bits 
{ 
    unsigned char MyOneBitVariable:1; 
    int My32BitInt; 
}; 

// MSVC specific implementation of data-packing in a type. 
#pragma pack(1) 
struct S32Bits 
{ 
    D_ALIGN(1) int My16BitVariable:16; 
    D_ALIGN(1) unsigned char Padding8Bits; 
    D_ALIGN(1) unsigned char MyOneBitVariable1:1; 
    D_ALIGN(1) unsigned char MyOneBitVariable2:1; 
    D_ALIGN(1) unsigned char MyOneBitVariable3:1; 
    D_ALIGN(1) unsigned char MyOneBitVariable4:1; 
    D_ALIGN(1) unsigned char MyFourBitVariable:4; 
}; 
#pragma pack(pop) 

'sizeof (S64Bits)' 8 होना चाहिए, जो यह है। 'sizeof (S32Bits)' 4, होना चाहिए यह नहीं है। एमएसवीसी पर बाद में 6 बाइट्स है। व्यवहार भी कंपाइलर-विशिष्ट है और अक्सर संकलक-अद्वितीय निर्देश होते हैं। इस प्रकार का व्यवहार लगभग आपको वह नहीं देता जो आप चाहते हैं। मैं अक्सर यकीन है कि संरचनाओं कि मैं वास्तव में एक निश्चित आकार के होने की आवश्यकता है कि बनाने के लिए मैक्रो का उपयोग:


#define TEST_TYPE_SIZE(Type, Size) assert(sizeof(Type) == Size); 

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

कार्ल बीलेफेल्ड बिट बिट शिफ्ट ऑपरेशंस का उपयोग करके 4-बिट मानों को 4int बिट में संग्रहीत करने का एक अच्छा प्राकृतिक समाधान प्रदान करता है, इसके बजाय उन का उपयोग करें।

+0

-1, और यदि मैं कर सकता हूं तो बिटफील्ड के उपयोग के लिए दूसरा -1। बस थोड़ा अंकगणित करें। यह आसान, पोर्टेबल, परिणाम अच्छी तरह से परिभाषित व्यवहार में है, और त्रुटि-प्रवण नहीं है। –

+1

गैर-योग्य हैक्स? मैं स्पष्ट रूप से संकलक-विनिर्देशों के बारे में बताता हूं। जब शिष्टाचार में डेटा पैक करने की बात आती है तो यह जानना बहुत महत्वपूर्ण है कि प्रत्येक कंपाइलर डेटा कैसे पैक करता है और संरेखित करता है। प्रश्न यह है कि अंतरिक्ष केवल एक बाधा के बाद से 4 बिट्स का उपयोग कैसे करें और मैं आपकी इच्छित स्मृति के आकार को प्राप्त करने की जटिलता के बारे में जानकारी प्रदान करने का प्रयास करता हूं। क्या आप कृपया अपने आलोचना को थोड़ा और विस्तारित कर सकते हैं? – Simon

+0

@ आर ..: शायद आपने इन विधियों का उपयोग करके सही आकार प्राप्त करने में कठिनाई के बारे में मेरी टिप्पणियां नहीं पढ़ी हैं? या शायद आपने संरचना-आकार पर निर्भर होने के बारे में अपना पाठ नहीं पढ़ा? मैंने सोचा कि वे बहुत अच्छी तरह से समझाया गया है कि आपको इस तरह के समाधान का उपयोग क्यों नहीं करना चाहिए। मेरा तर्क इन समाधानों का उपयोग कर प्रो नहीं था, वे इसके खिलाफ हैं। – Simon

0

क्या आप कभी भी 4-बिट मानों का पता लेना चाहते हैं? यदि ऐसा है, तो आपको उन्हें "उचित" डेटा प्रकार, जैसे कि char में स्टोर करना होगा।

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