जब CI में प्रोग्रामिंग पाया गया है कि यह GCCs का उपयोग करके पैक्स को पैक करने के लिए अमूल्य है __attribute__((__packed__))
[...]
चूंकि आप उल्लेख करते हैं __attribute__((__packed__))
, मेरा मानना है कि आपका इरादा एक के भीतर सभी पैडिंग को खत्म struct
करना है (प्रत्येक सदस्य के पास 1-बाइट संरेखण है)।
क्या पैकिंग संरचनाओं के लिए कोई मानक नहीं है जो सभी सी कंपाइलरों में काम करता है?
... और जवाब नहीं है"। एक संरचना के सापेक्ष पैडिंग और डेटा संरेखण (और स्टैक या ढेर में संरचनाओं के सन्निहित सरणियाँ) एक महत्वपूर्ण कारण के लिए मौजूद हैं। कई मशीनों पर, अनलॉग्ड मेमोरी एक्सेस संभावित रूप से महत्वपूर्ण प्रदर्शन जुर्माना हो सकता है (हालांकि कुछ नए हार्डवेयर पर कम होता जा रहा है)। कुछ दुर्लभ मामलों में, गलत तरीके से मेमोरी एक्सेस एक बस त्रुटि की ओर जाता है जो अपरिवर्तनीय है (पूरे ऑपरेटिंग सिस्टम को क्रैश भी कर सकता है)।
चूंकि सी मानक पोर्टेबिलिटी पर केंद्रित है, इसलिए संरचना में सभी पैडिंग को खत्म करने के लिए एक मानक तरीका होना बहुत कम समझ में आता है और सिर्फ मनमाने क्षेत्रों को गलत तरीके से पेश करने की अनुमति देता है, क्योंकि ऐसा करने से संभावित रूप से सी कोड गैर-पोर्टेबल बनाने का जोखिम होगा।
इस तरह के डेटा को एक बाहरी स्रोत में आउटपुट करने का सबसे सुरक्षित और सबसे पोर्टेबल तरीका है कि सभी पैडिंग को खत्म करने के लिए बाइट स्ट्रीम से / के बजाय केवल आपके की कच्ची मेमोरी सामग्री पर भेजने की कोशिश करना है structs
। यह आपके कार्यक्रम को इस क्रमिक संदर्भ के बाहर प्रदर्शन के दंड से पीड़ित होने से भी रोकता है, और आपको struct
बिना किसी फेंक-बंद किए और संपूर्ण सॉफ़्टवेयर को गड़बड़ किए बिना स्वतंत्र रूप से नए फ़ील्ड जोड़ने की अनुमति भी देगा । यह आपको अंतर्मन और उससे जुड़ी चीजों से निपटने के लिए कुछ जगह देगा, अगर वह कभी चिंता का विषय बन जाए।
संकलक-विशिष्ट निर्देशों तक पहुंचने के बिना सभी पैडिंग को खत्म करने का एक तरीका है, हालांकि यह केवल तभी लागू होता है जब खेतों के बीच सापेक्ष क्रम कोई फर्क नहीं पड़ता। कुछ इस तरह दिया गया:
struct Foo
{
double x; // assume 8-byte alignment
char y; // assume 1-byte alignment
// 7 bytes of padding for first field
};
... हमें इन क्षेत्रों से युक्त संरचना के पते के सापेक्ष संरेखित मेमोरी एक्सेस के लिए पैडिंग की आवश्यकता है, जैसे:
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
x_______y.......x_______y.......x_______y.......x_______y.......
... जहाँ .
इंगित करता है गद्दी। प्रत्येक x
को प्रदर्शन के लिए 8-बाइट सीमा (और कभी-कभी सही व्यवहार) के लिए भी संरेखित करना चाहिए।
आप एक SoA (सरणी की संरचना) प्रतिनिधित्व का उपयोग करके पोर्टेबल तरीके से पैडिंग को समाप्त कर सकते हैं (मान लें कि हमें 8 शेष राशि की आवश्यकता है Foo
):
struct Foos
{
double x[8];
char y[8];
};
हमने संरचना को प्रभावी ढंग से ध्वस्त कर दिया है। इस स्थिति में, मेमोरी प्रतिनिधित्व इस प्रकार हो जाता है:
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
x_______x_______x_______x_______x_______x_______x_______x_______
... और इस:
01234567
yyyyyyyy
... कोई अधिक पैडिंग ओवरहेड, और बिना गलत मेमोरी मेमोरी को शामिल किए बिना, क्योंकि हम इन डेटा फ़ील्ड्स को संरचना पते की ऑफसेट के रूप में एक्सेस नहीं कर रहे हैं, बल्कि इसके बजाय आधार पते की एक ऑफसेट के रूप में प्रभावी रूप से एक सरणी है।
यह उपभोग करने के लिए दोनों कम डेटा के परिणामस्वरूप अनुक्रमिक पहुंच के लिए तेजी से बोनस का वहन करता है (मशीन की प्रासंगिक डेटा खपत दर को धीमा करने के लिए मिश्रण में कोई अधिक अप्रासंगिक गद्दी नहीं है) और संकलक के लिए संभावित रूप से प्रसंस्करण के लिए एक क्षमता बहुत तुच्छ है। ।
नकारात्मक पक्ष यह है कि यह कोड के लिए एक PITA है। यह खेतों के बीच बड़ी स्ट्राइड के साथ यादृच्छिक अभिगम के लिए संभावित रूप से कम कुशल है, जहां अक्सर AoS या AoSoA प्रतिनिधि बेहतर प्रदर्शन करेंगे। लेकिन यह एक मानक तरीका है पैडिंग को खत्म करने और चीजों को कसकर पैक करने के लिए जितना संभव हो सब कुछ संरेखण के साथ पेंच किए बिना।