2013-09-04 5 views
6

उदाहरण के लिए:कंपाइलर बिटफील्ड संरचना के आकार को कैसे निर्धारित करता है?

struct a { 
    uint32_t foreColor_ : 32; 
    uint32_t backColor_ : 32; 
    uint16_t lfHeight_ : 16; 
    uint16_t flags_: 4; 
    bool lfBold_: 1; 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; 
}; 

16 बाइट्स लेकिन

struct a { 
    uint32_t foreColor_ : 32; 
    uint32_t backColor_ : 32; 
    uint16_t lfHeight_ : 16; 
    uint8_t  flags_: 4; 
    bool lfBold_: 1; 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; //for ime 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; 
}; 

12 बाइट्स लंबे है।

मैंने सोचा कि flags_ की लंबाई समान होनी चाहिए, लेकिन ऐसा नहीं लगता है।

क्यों?

+0

थोड़ा सा क्षेत्र के लिए 'uint32_t' जैसे प्रकारों का उपयोग नहीं कर रहा है? (आम तौर पर, उन्हें केवल तब ही उपयोग किया जाना चाहिए जब आपको बाहरी प्रारूप से बिल्कुल मिलान करने की आवश्यकता हो, और फिर भी, उनका उपयोग संदिग्ध है।) –

उत्तर

6

मानक (the working draft के 9.6) इस कहते हैं:

थोड़ा-क्षेत्र निर्दिष्ट करता है; इसकी लंबाई को कॉलन द्वारा बिट-फील्ड नाम से सेट किया गया है। बिट-फील्ड विशेषता वर्ग सदस्य के प्रकार का हिस्सा नहीं है। निरंतर अभिव्यक्ति एक अभिन्न स्थिर-अभिव्यक्ति होगी जो शून्य से अधिक या उसके बराबर मान के साथ होगी। स्थिर-अभिव्यक्ति बिट-फ़ील्ड के प्रकार के ऑब्जेक्ट प्रस्तुति ( 3.9) में बिट्स की संख्या से बड़ी हो सकती है; ऐसे मामलों में अतिरिक्त बिट्स को पैडिंग बिट्स के रूप में उपयोग किया जाता है और बिट-फील्ड के मान प्रतिनिधित्व ( 3.9) में भाग नहीं लेते हैं। कक्षा वस्तु के भीतर बिट-फ़ील्ड का आवंटन कार्यान्वयन-परिभाषित है। बिट-फ़ील्ड का संरेखण कार्यान्वयन-परिभाषित है। बिट-फ़ील्ड कुछ एड्रेसेबल आवंटन इकाई में पैक किए जाते हैं। [नोट: कुछ मशीनों पर बिट-फ़ील्ड स्ट्रैडल आवंटन इकाइयां और दूसरों पर नहीं। बिट-फ़ील्ड पर कुछ मशीनों को बाएं से दाएं दाएं से बाएं असाइन किए जाते हैं। अंत टिप्पणी]

(मेरा जोर)

तो यह आपके संकलक पर निर्भर करेगा। आपके मामले में क्या हो रहा है - और मैं काफी सामान्य व्यवहार के रूप में वर्णन करता हूं - यह है कि यह केवल उसी प्रकार के बिटफील्ड को जोड़ रहा है और फिर संरचना को 4 बाइट सीमा तक पैक कर रहा है, इसलिए पहले मामले में हमारे पास है:

struct a { 
    uint32_t foreColor_ : 32; // 4 bytes (total) 
    uint32_t backColor_ : 32; // 8 bytes 
    uint16_t lfHeight_ : 16; // 10 bytes 
    uint16_t flags_: 4;  // 12 bytes 
    bool lfBold_: 1;   // 13 bytes 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; // still 13 bytes 
}; 

तो है जो 16 बाइट्स गद्देदार, और दूसरे में हमने:

struct a { 
    uint32_t foreColor_ : 32; // 4 bytes (total) 
    uint32_t backColor_ : 32; // 8 bytes 
    uint16_t lfHeight_ : 16; // 10 bytes 
    uint8_t  flags_: 4;  // 11 bytes 
    bool lfBold_: 1;   // 12 bytes 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; // still 12 bytes 
}; 

कौन सा कोई पैडिंग की जरूरत है और 12 बाइट्स में रहता है।

+1

यह कार्यान्वयन परिभाषित है, इसमें कोई संदेह नहीं है, लेकिन यह कार्यान्वयन की गुणवत्ता के लिए बहुत कुछ नहीं कहता है जब उसके दो संरचनाओं के अलग-अलग आकार होते हैं। –

+0

* शग * मुझे लगता है कि मैंने इस तरह के व्यवहार के साथ सबसे अधिक कार्यान्वयन किया है। वे खेतों की तरह गठबंधन करेंगे लेकिन खेतों के विपरीत नहीं। मैंने वास्तव में सोचा था कि यह तब तक मानक में परिभाषित किया गया था जब तक मैंने चेक नहीं किया। –

+0

मुझे नहीं लगता कि मैंने कभी एक कार्यान्वयन देखा है जो अब इस तरह से काम करता है। जी ++ निश्चित रूप से नहीं करता है। –

0

यह कंपाइलर विशिष्ट है, कंपाइलर फ़ील्ड तक पहुंच अनुकूलित करने के लिए विभिन्न संरेखण कर रहा है।

यदि आप चाहते हैं (संरेखण) पर भरोसा करना चाहते हैं। (जैसे नेटवर्क हेडर प्रोसेसिंग) आपको #pragma push, pop का उपयोग करने की आवश्यकता है।

या __ विशेषता __ (पैक) - जो एक जीसीसी एक्सटेंशन है।

struct { 
... 
} __attribute__(packed) 

यह संकलक को स्क्वैश करने के लिए मजबूर करेगा।

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