C++
बिट क्षेत्र
खोज…
परिचय
बिट फ़ील्ड आकार को कम करने के लिए C और C ++ संरचनाओं को कसकर पैक करते हैं। यह दर्द रहित दिखाई देता है: सदस्यों के लिए बिट्स की संख्या निर्दिष्ट करें, और कंपाइलर बिट्स के सह-मिलिंग का काम करता है। प्रतिबंध एक बिट क्षेत्र के सदस्य का पता लेने में असमर्थता है, क्योंकि यह सह-संग्रहित है। sizeof()
भी अस्वीकृत है।
बिट फ़ील्ड्स की लागत धीमी पहुंच है, क्योंकि सदस्य मूल्यों को निकालने या संशोधित करने के लिए मेमोरी को पुनः प्राप्त किया जाना चाहिए और बिटवाइज़ संचालन को लागू किया जाना चाहिए। ये ऑपरेशन निष्पादन योग्य आकार को भी जोड़ते हैं।
टिप्पणियों
बिटवाइज़ ऑपरेशन कितने महंगे हैं? मान लीजिए एक साधारण गैर-बिट क्षेत्र संरचना:
struct foo {
unsigned x;
unsigned y;
}
static struct foo my_var;
कुछ बाद के कोड में:
my_var.y = 5;
यदि sizeof (unsigned) == 4
, तो x को संरचना के प्रारंभ में संग्रहीत किया जाता है, और y को 4 बाइट्स में संग्रहित किया जाता है। असेंबली कोड जनरेट किया जा सकता है:
loada register1,#myvar ; get the address of the structure
storei register1[4],#0x05 ; put the value '5' at offset 4, e.g., set y=5
यह सीधा है क्योंकि x y के साथ सह-मिलिंग नहीं है। लेकिन बिट फ़ील्ड के साथ संरचना को फिर से परिभाषित करने की कल्पना करें:
struct foo {
unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
unsigned y : 4;
}
x
और y
दोनों को एक बिट बाइट साझा करते हुए 4 बिट्स आवंटित किए जाएंगे। संरचना इस प्रकार 1 बाइट तक ले जाता है, बजाय 8. सेट करने के लिए विधानसभा पर विचार करें y
अब, यह मानते हुए यह ऊपरी निबल में समाप्त होता है:
loada register1,#myvar ; get the address of the structure
loadb register2,register1[0] ; get the byte from memory
andb register2,#0x0f ; zero out y in the byte, leaving x alone
orb register2,#0x50 ; put the 5 into the 'y' portion of the byte
stb register1[0],register2 ; put the modified byte back into memory
यदि हमारे पास इन संरचनाओं के हजारों या लाखों हैं, तो यह एक अच्छा व्यापार-बंद हो सकता है, और यह कैश में मेमोरी को बनाए रखने में मदद करता है या स्वैपिंग को रोकता है - या इन समस्याओं को धीमा करने के लिए निष्पादन योग्य को धीमा कर सकता है और प्रसंस्करण धीमा कर सकता है। सभी चीजों की तरह, अच्छे निर्णय का उपयोग करें।
डिवाइस ड्राइवर का उपयोग करें: डिवाइस ड्राइवरों के लिए एक चतुर कार्यान्वयन रणनीति के रूप में बिट फ़ील्ड से बचें। बिट क्षेत्र भंडारण लेआउट अनिवार्य रूप से संकलक के बीच संगत नहीं हैं, जिससे ऐसे कार्यान्वयन गैर-पोर्टेबल होते हैं। मानों को सेट करने के लिए रीड-मॉडिफाई-लेखन संभवत: अप्रत्याशित व्यवहार के कारण, उपकरण क्या उम्मीद करते हैं।
घोषणा और उपयोग
struct FileAttributes
{
unsigned int ReadOnly: 1;
unsigned int Hidden: 1;
};
यहां, इन दोनों क्षेत्रों में से प्रत्येक मेमोरी में 1 बिट पर कब्जा करेगा। यह चर नामों के बाद : 1
अभिव्यक्ति द्वारा निर्दिष्ट किया गया है। बेस प्रकार का बिट फ़ील्ड किसी भी अभिन्न प्रकार (8-बिट इंट से 64-बिट इंट) हो सकता है। unsigned
प्रकार का उपयोग करने की सिफारिश की जाती है, अन्यथा आश्चर्य आ सकता है।
यदि अधिक बिट्स की आवश्यकता होती है, तो आवश्यक बिट्स की संख्या के साथ "1" को बदलें। उदाहरण के लिए:
struct Date
{
unsigned int Year : 13; // 2^13 = 8192, enough for "year" representation for long time
unsigned int Month: 4; // 2^4 = 16, enough to represent 1-12 month values.
unsigned int Day: 5; // 32
};
पूरी संरचना सिर्फ 22 बिट्स का उपयोग कर रही है, और सामान्य संकलक सेटिंग्स के साथ, इस संरचना का sizeof
4 बाइट्स होगा।
उपयोग बहुत सरल है। बस चर को घोषित करें, और इसे साधारण संरचना की तरह उपयोग करें।
Date d;
d.Year = 2016;
d.Month = 7;
d.Day = 22;
std::cout << "Year:" << d.Year << std::endl <<
"Month:" << d.Month << std::endl <<
"Day:" << d.Day << std::endl;