2011-06-05 19 views
10

32-बिट, 16-बिट और 8-बिट सदस्य मानों से बना एक संरचना की कल्पना करना संभव है। जहां सदस्य मूल्यों का क्रम ऐसा होता है कि प्रत्येक सदस्य इसकी प्राकृतिक सीमा पर है।स्ट्रक्चर सदस्य संरेखण - क्या कोई पैडिंग

struct Foo 
{ 
    uint32_t a; 
    uint16_t b; 
    uint8_t c; 
    uint8_t d; 
    uint32_t e; 
}; 

सदस्य संरेखण और गद्दी नियम विज़ुअल सी के लिए documented हैं ++। वीसी ++ पर आकार (फू) उपरोक्त संरचना अनुमानित रूप से "12" है।

अब, मुझे पूरा यकीन है कि नियम यह है कि पैडिंग और संरेखण के बारे में कोई धारणा नहीं की जानी चाहिए, लेकिन व्यावहारिक रूप से, अन्य ऑपरेटिंग सिस्टम पर अन्य कंपाइलर्स समान गारंटी देते हैं?

यदि नहीं, तो क्या जीसीसी पर "#pragma पैक (1)" के बराबर है?

+0

सी में, 'फू', 'sizeof (Foo)' में घोषित नहीं किया गया है। अभिव्यक्ति एक त्रुटि है (जब तक कि 'Foo' को कहीं और परिभाषित नहीं किया जाता है)।मेरा सुझाव है कि आप बहु भाषा स्रोत फ़ाइलों को लिखने की कोशिश न करें: विपक्ष आपको मिलने वाले किसी भी समर्थक से कहीं अधिक बड़ा है। – pmg

+0

@pmg: पेडेंट्री। :) 'typedef struct foo {...} Foo;' – Xeo

+0

मेरा मानना ​​है कि 'टाइपिफ़' सी ++ में अनावश्यक (और इसलिए बग का सुरक्षित रूप से हटाने योग्य स्रोत) है। मेरा मुद्दा बनी हुई है: बहु-भाषा स्रोत फ़ाइलों को लिखना इसके लायक से अधिक परेशानी है। – pmg

उत्तर

6

उन प्रणालियों पर जो वास्तव में उन प्रकार की पेशकश करते हैं, यह काम करने की अत्यधिक संभावना है। कहें, 36-बिट सिस्टम उन प्रकारों को पहले स्थान पर उपलब्ध नहीं होगा।

जीसीसी एक विशेषता

__attribute__ ((packed))

समान प्रभाव के साथ प्रदान करता है।

+0

यह वास्तव में निर्भर नहीं है, बल्कि आर्किटेक्चर निर्भर है। उदाहरण के लिए कुछ 16 या 32 बिट प्रोसेसर सीधे 8 बिट पते को संबोधित नहीं कर सकते हैं, इसलिए पैडिंग के बिना 16 या 32 बिट मेमोरी पढ़ने से 8 बिट मान निकालने के लिए अतिरिक्त शिफ्ट और मास्क निर्देश उत्पन्न करना पड़ सकता है। यह स्थिति कहीं अधिक आम है कि आपकी काल्पनिक 36 बिट सिस्टम (उदाहरण के लिए एआरएम 7)। – Clifford

+0

@ क्लाइफोर्ड: यह आम नहीं है। कंपाइलर को पहले से मौजूद होने पर 8-बिट प्रकार को संबोधित करने के लिए कोड उत्पन्न करना होता है (क्योंकि इसे कभी भी सरणी में गठबंधन नहीं किया जा सकता है), इसलिए यह कोई अतिरिक्त संयम नहीं है। आम तौर पर, किसी प्रकार का "संरेखण" कभी भी अपने आकार से बड़ा नहीं हो सकता है (और इसके आकार को विभाजित करना चाहिए), इसलिए जब किसी संरचना में प्रकार का उपयोग किया जाता है तो यह बड़े संरेखण को लागू करने के लिए एक संकलक के लिए रोगजनक होगा। –

+0

मैं यह नहीं कह रहा था कि संकलक आवश्यक होने पर 8 बिट एक्सेस के लिए कोड उत्पन्न नहीं कर सका या नहीं, बल्कि प्रदर्शन कारणों से यह एक संरचना के लिए इससे बच जाएगा। एक सरणी संगत होने की गारंटी है, एक संरचना नहीं है। मैं सुझाव दूंगा कि एआरएम 7 काफी आम है, लेकिन चूंकि इसे लिनक्स टैग किया गया है, इस संदर्भ में इतना ज्यादा नहीं है। – Clifford

7

सामान्य रूप से आप सही हैं कि यह एक सुरक्षित धारणा नहीं है, हालांकि आपको अक्सर कई प्रणालियों पर पैकिंग मिलती है। जब आप gcc का उपयोग करते हैं तो आप packed विशेषता का उपयोग अपने प्रकारों पर कर सकते हैं।

उदा।

struct __attribute__((packed)) Blah { /* ... */ }; 
+0

यह बल्कि खतरनाक और पूरी तरह से अनावश्यक है। मेरा जवाब देखें –

+0

@ आर ..: मैं पूरी तरह से सहमत हूं। –

5

अभ्यास में, किसी भी प्रणाली जहां uintXX_t प्रकार मौजूद हैं पर, आप कुछ ही गद्दी के साथ वांछित संरेखण मिल जाएगा। गारंटी देने की कोशिश करने के लिए बदसूरत जीसीसी-इस्म्स में फेंक न दें।

संपादित करें: कारण है कि यह उपयोग करने के लिए attribute packed या aligned, यह पूरे struct जब एक बड़ा struct के एक सदस्य के रूप में या ढेर पर इस्तेमाल किया गलत संरेखित कारण हो सकता है हानिकारक हो सकता है पर विस्तार से बता दें। यह निश्चित रूप से प्रदर्शन को नुकसान पहुंचाएगा और गैर-x86 मशीनों पर, बहुत बड़ा कोड उत्पन्न करेगा। इसका मतलब यह भी है कि यह अमान्य संरचना के किसी भी सदस्य को पॉइंटर लेने के लिए है, क्योंकि कोड जो पॉइंटर के माध्यम से मूल्य तक पहुंचता है, उसे पता नहीं होगा कि इसे गलत तरीके से गलत किया जा सकता है और इस प्रकार गलती हो सकती है।

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

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