2012-06-22 16 views
8

मैंने फ़ॉर्म के अनगिनत प्रश्नों को देखा है "मुझे पैडिंग पसंद नहीं है मैं इसे कैसे बंद कर सकता हूं", लेकिन अभी तक अतिरिक्त पैडिंग प्रदान करने के लिए कंपाइलर को मजबूर करने के बारे में कुछ भी नहीं मिला है ।सी (++) स्ट्रक्चर फोर्स अतिरिक्त पैडिंग

विशिष्ट मामले मैं की तरह

struct particle{ 
    vect2 s; 
    vect2 v; 
    int rX; 
    int rY; 
    double mass; 
    int boxNum; 
}; 

कहाँ vect2 एक सरल struct {double x; double y;} vect2 है लगता है। एसएसई 2 का उपयोग करने के लिए, मुझे 16 बाइट सीमाओं के साथ गठबंधन, युगल की एक जोड़ी लोड करने में सक्षम होना चाहिए। यह तब तक काम करता था जब तक मैंने अतिरिक्त int जोड़ा, मेरे संरचना आकार को 48 बाइट से 56 बाइट तक दबाया। परिणाम segfaults है।

क्या कोई ऐसा संकलक निर्देश है जिसका मैं उपयोग कर सकता हूं या तो कहता है कि "इस स्ट्रक्चर को इसे 16 बाइट्स लम्बाई बनाने के लिए पैड" या "इस संरचना में 16-बाइट्स का संरेखण है"? मुझे पता है कि मैं इसे मैन्युअल रूप से कर सकता हूं (उदाहरण के लिए, एक अतिरिक्त char [12] पर काम करना), लेकिन मैं वास्तव में बस संकलक (जीसीसी, अधिमानतः आईसीसी संगत) को बताऊंगा, और यदि मैं इसे बदलता हूं तो इसे मैन्युअल रूप से नहीं करना होगा भविष्य में संरचना।

+7

सी ++ में 11 इस उद्देश्य के लिए अब ['alignas'] (http://en.cppreference.com/w/cpp/language/alignas) है। – ildjarn

+0

मुझे नहीं लगता कि जीसीसी ने अभी तक इसे लागू किया है, हालांकि। – chris

+2

फिर http://stackoverflow.com/questions/6959261/how-can-i-simulate-alignast –

उत्तर

3

यदि कोई समाधान ढूंढने की स्थिति में है, तो मैं इसका अपना जवाब जोड़ रहा हूं।मार्क का समाधान एक साफ है, और स्वचालित आवश्यकता को पूरा करता है, लेकिन ऐसा नहीं होता है जब मैं साथ जाता हूं। मैं इस से बचने के लिए, जिसके कारण मैं प्रश्न पूछा चाहता था, लेकिन वहाँ एक "तुच्छ" समाधान है:

struct particle{ 
    vect2 s; 
    vect2 v; 
    int rX; 
    int rY; 
    double mass; 
    int boxNum; 
    char padding[12]; 
}; 

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

ध्यान दें कि मेरी struct 56 बाइट्स था, और क्योंकि अनुगामी int पहले से ही 8-बाइट सीमा को 4 बाइट से बाहर गद्देदार किया जा रहा था मैं, 12 कहा कि यह 64 गणित काम नहीं करता है कि बनाने के लिए; struct वास्तव में केवल 52 बाइट था। केवल 5 char एस जोड़कर काम किया होगा, struct 57 बाइट्स लंबा बनाकर, जो 64 तक गड़बड़ कर दिया गया होगा, लेकिन यह एक अच्छा समाधान नहीं है, इसलिए मैंने 12 का उपयोग बिल्कुल ठीक करने के लिए किया था।

+6

यह प्रदर्शन आवश्यकताओं को समझ में आता है; अपने सहकर्मियों और भविष्य के रखरखाव (आपके भविष्य के स्वयं सहित) के लिए * कृपया * फिक्स पर टिप्पणी करें और एक संकलन समय जोड़ें कि 'संरचना' आकार में 16 बाइट्स का एक बहु है। – ecatmur

+0

धन्यवाद, यह एक बहुत अच्छा मुद्दा है। – zebediah49

+1

क्या कोई विशेष कारण है कि आप इसे संकलक को छोड़ना नहीं चाहते थे, उदा। '__attribute __ के साथ ((गठबंधन (16)))'? – Pedro

1

इस के लिए नए सी ++ 11 स्पेक में new feature भी है, हालांकि मुझे विश्वास नहीं है कि कई विक्रेताओं को अभी तक लागू किया गया है।

आप पैक प्रागमा को आजमा सकते हैं, हालांकि यह spec द्वारा समर्थित नहीं है। जीसीसी और एमएस दोनों हालांकि इसका समर्थन करते हैं।

यह 1 बाइट सीमाओं पर संरचना को संरेखित करता है, हालांकि आप अपनी इच्छानुसार किसी भी चीज़ को बदल सकते हैं।

#pragma pack(push,1) 
// ... 
#pragma pack(pop) 

अद्यतन:

तो जाहिरा तौर पर इसके बाद के संस्करण के रूप में यह केवल गद्दी सिकुड़ता है, यह कभी नहीं का विस्तार काम नहीं करेगा। अफसोस की बात है, मेरे पास आज दोपहर एक परीक्षण वातावरण नहीं है।

शायद एक अनाम संघ का उपयोग करना काम करेगा। मुझे पता है कि यह सबसे बड़े आकार में विस्तारित होगा, हालांकि मुझे नहीं पता कि आपको संरेखण के बारे में कोई गारंटी है या नहीं।

template<typename T, size_t padding_size> 
    struct padded_field { 
    union { 
     T value; 
     uint8_t padding[padding_size]; 
    }; 
    }; 
+3

मैंने कोशिश की; जब 4 पर सेट किया जाता है, तो यह 52 बाइट तक गिर जाता है .. लेकिन जब 16 पर सेट होता है, तो यह 56 पर रहता है, इसलिए मुझे लगता है कि यह पैडिंग का विस्तार नहीं करता है, केवल ताकतवर पैकिंग को मजबूर करता है। – zebediah49

+1

मैं जीसीसी के कार्यान्वयन से अपरिचित हूं, लेकिन प्रति [दृश्य सी ++ दस्तावेज] (http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx), "एक सदस्य का संरेखण सीमा पर होगा या तो सदस्य के आकार के बहु या एकाधिक के एकाधिक हैं, ** जो भी छोटा है **। " –

1

जांची नहीं है, लेकिन यह काम हो सकता है:

#include <xmmintrin.h> 

struct particle{ 
    union { 
    vect2 s; 
    __m128 s_for_alignment; 
    }; 
    union { 
    vect2 v; 
    __m128 v_for_alignment; 
    }; 
    ... 
}; 

मुझे पता है कि जीसीसी __m128 संरेखित पहले सही ढंग से समस्या आई हो, लेकिन उन अब तक किया जाना चाहिए।

+0

उस स्थिति में मैं 'संघ vect2 {__m128d s के साथ भी जा सकता हूं; संरचना {डबल एक्स; डबल वाई;};}; ', लेकिन हाँ, यह जाने का रास्ता हो सकता है। – zebediah49

+0

परीक्षण इंगित करता है कि यह मैन्युअल रूप से पैडिंग से लगभग 10% धीमा काम करता है; मुझे पूरी तरह से यकीन नहीं है क्यों। – zebediah49

+0

पागल। जेनरेट एएसएम में कोई अंतर? – ecatmur

8

आप अपने आप को आकार का ट्रैक रखने के बिना स्वचालित रूप से पैड करने के लिए दो संरचनाओं को घोंसला कर सकते हैं।

struct particle 
{ 
    // ... 
}; 

{ 
    particle p; 
    char padding[16-(sizeof(particle)%16)]; 
}; 

इस संस्करण दुर्भाग्य से 16 बाइट्स कहते हैं अगर संरचना पहले से ही 16 की एक बहु है यह अपरिहार्य है, क्योंकि मानक शून्य लम्बाई के एरे अनुमति नहीं है।

कुछ compilers एक विस्तार के रूप शून्य लंबाई सरणियों की अनुमति देते हैं, और कहा कि मामले में आप इस के बजाय कर सकते हैं:

struct particle_wrapper 
{ 
    particle p; 
    char padding[sizeof(particle)%16 ? 16-(sizeof(particle)%16) : 0]; 
}; 

इस संस्करण में गद्दी के किसी भी बाइट नहीं जोड़ता है अगर संरचना पहले से ही 16 की एक बहु है

+1

आप 'चार पैडिंग [(आकार (कण) + 15) और ~ 15]' करके 16 बाइट जोड़ने से बच सकते हैं। – Pedro

+0

@ पेड्रो, मुझे नहीं लगता कि यह काफी सही है। –

+1

यह है, लेकिन केवल काम करता है क्योंकि 16 2 की शक्ति है। यदि आप मानते हैं कि बाइनरी में '15'' 1..10000' है, तो यह समझना आसान है, यानी यह पिछले चार बिट्स को फ़िल्टर करता है, जिससे एकाधिक 16. चूंकि यह संख्या 16 में से एक के लिए संख्या को छोटा कर देता है, इसलिए हमें पहले 15 जोड़ना होगा ताकि हमें अगले उच्चतम एकाधिक मिल जाए। – Pedro

3

gcc में, आप __attribute__((aligned(...))) के साथ मनमाने ढंग से प्रकार और चर संरेखित कर सकते हैं। आपके उदाहरण के लिए, यह

struct particle{ 
    vect2 s; 
    vect2 v; 
    int rX; 
    int rY; 
    double mass; 
    int boxNum; 
} __attribute__((aligned (16))); 

यह स्वचालित रूप से संरचना को पैड करता है ताकि उसके सरणी सही तरीके से गठबंधन हो जाएं।