2012-08-06 8 views
8

this question से कोई यह मानना ​​शुरू कर सकता है कि संघ का संरेखण इसके व्यक्तिगत सदस्यों के सबसे बड़े संरेखण से कम नहीं है। लेकिन मुझे long long प्रकार जीसीसी/जी ++ में टाइप करने में समस्या है। पूर्ण उदाहरण here पाया जा सकता है, लेकिन यहाँ मेरे सवाल के लिए प्रासंगिक भागों हैं:लंबे समय तक संघ के सदस्य का संरेखण क्यों संघ/संरचना से बड़ा है? क्या ये सही है?

union ull { 
    long long m; 
}; 

struct sll { 
    long long m; 
}; 


int main() { 
#define pr(v) cout << #v ": " << (v) << endl 
    pr(sizeof(long long)); 
    pr(__alignof__(long long)); 
    pr(sizeof(ull)); 
    pr(__alignof__(ull)); 
    pr(sizeof(sll)); 
    pr(__alignof__(sll)); 
}; 

यह निम्न उत्पादन में परिणाम है:

sizeof(long long): 8 
__alignof__(long long): 8 
sizeof(ull): 8 
__alignof__(ull): 4 
sizeof(sll): 8 
__alignof__(sll): 4 

एक संघ सदस्य है कि से भी बड़ा के संरेखण क्यों है युक्त संघ का?

[अद्यतन]

कीथ के जवाब alignof के अनुसार यहाँ गलत है। लेकिन मैं निम्नलिखित का परीक्षण करता हूं और ऐसा लगता है कि alignof हमें सच बताता है। देखें:

union ull { 
    long long m; 
}; 
long long a; 
char b; 
long long c; 
char d; 
ull e; 
int main() { 
#define pr(v) cout << #v ": " << (v) << endl 
    pr(size_t((void*)&b)); 
    pr(size_t((void*)&c)); 
    pr(size_t((void*)&d)); 
    pr(size_t((void*)&e)); 
    pr(size_t((void*)&c) - size_t((void*)&b)); 
    pr(size_t((void*)&e) - size_t((void*)&d)); 
}; 

उत्पादन:

size_t((void*)&b): 134523840 
size_t((void*)&c): 134523848 
size_t((void*)&d): 134523856 
size_t((void*)&e): 134523860 
size_t((void*)&c) - size_t((void*)&b): 8 
size_t((void*)&e) - size_t((void*)&d): 4 

तो, long long के संरेखण 8 और long long युक्त संघ के संरेखण वैश्विक डेटा में 4 है। स्थानीय दायरे के लिए मैं इसका परीक्षण नहीं कर सकता क्योंकि ऐसा लगता है कि संकलक स्थानीय डेटा को पुनर्व्यवस्थित करने के लिए स्वतंत्र है - इसलिए यह चाल काम नहीं करती है। क्या आप इस पर टिप्पणी कर सकते हैं?

[/ अद्यतन]

+1

मुझे रेड हैट पर एक ही चीज़ दिखाई देती है, जीसी 4.7.0 '-एम 32' के साथ, लेकिन * नहीं * '-m64' (सभी' 8') के साथ। – BoBTFish

+1

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 _Alignof (C11) के लिए संबंधित gcc बग का एक लिंक। –

उत्तर

7

__alignof__ (जो एक जीसीसी विस्तार है) आवश्यक रूप से एक प्रकार के लिए आवश्यक संरेखण रिपोर्ट नहीं करता।

x86 प्रोसेसर, उदाहरण के लिए किसी भी प्रकार के लिए वास्तव में 1-बाइट संरेखण की आवश्यकता नहीं है। ऑब्जेक्ट शब्द-संरेखित होने पर 4-बाइट या 8-बाइट ऑब्जेक्ट तक पहुंच अधिक प्रभावी होगी, लेकिन बाइट संरेखण पर्याप्त है।

का हवाला देते हुए gcc documentation:

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

लेकिन यह अभी भी वास्तव में प्रश्न का उत्तर नहीं देता है। उस ढीली परिभाषा के साथ भी, long long युक्त संरचना या संघ के मुकाबले long long के लिए एक कठोर संरेखण को इंगित करने के लिए मैं __alignof__ के किसी भी अच्छे कारण के बारे में नहीं सोच सकता।

एक प्रकार के संरेखण निर्धारित करने का एक और अधिक पोर्टेबल विधि यह है:

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t))) 

इस प्रकार t के एक सदस्य की भरपाई पैदावार एक char और एक t से मिलकर struct में।इस मैक्रो का उपयोग करना, इस कार्यक्रम: long long है:

sizeof(long long): 8 
__alignof__(long long): 8 
ALIGNOF(long long): 4 
sizeof(ull): 8 
__alignof__(ull): 4 
ALIGNOF(ull): 4 
sizeof(sll): 8 
__alignof__(sll): 4 
ALIGNOF(sll): 4 

परिणाम मेरी ALIGNOF() मैक्रो संगत कर रहे हैं ने संकेत दिया:

#include <iostream> 
#include <cstddef> 

union ull { 
    long long m; 
}; 

struct sll { 
    long long m; 
}; 

#define ALIGNOF(type) ((int)(offsetof(struct {char c; type t;}, t))) 

int main() { 
#define pr(v) std::cout << #v ": " << (v) << std::endl 
    pr(sizeof(long long)); 
    pr(__alignof__(long long)); 
    pr(ALIGNOF(long long)); 
    pr(sizeof(ull)); 
    pr(__alignof__(ull)); 
    pr(ALIGNOF(ull)); 
    pr(sizeof(sll)); 
    pr(__alignof__(sll)); 
    pr(ALIGNOF(sll)); 
}; 

अपने सिस्टम (जीसीसी-4.7, Ubuntu 12.04, 86) पर इस उत्पादन का उत्पादन 4-बाइट संरेखण, और long long युक्त संरचना या संघ में 4-बाइट संरेखण है।

मुझे संदेह है कि यह __alignof__ के जीसीसी के कार्यान्वयन में एक बग है, या कम से कम एक असंगतता है। लेकिन परिभाषा की अस्पष्टता यह सुनिश्चित करना मुश्किल बनाती है कि यह वास्तव में एक बग है। It doesn't seem to have been reported

अद्यतन:

मैं बंदूक कूद हो सकता है लेकिन मैं सिर्फ एक bug report सबमिट किए हैं।

यह earlier bug report, "INVALID" के रूप में बंद है, समान है, लेकिन यह संरचना के संरेखण को संदर्भित नहीं करता है।

अद्यतन 2:

मेरे बग रिपोर्ट पहले से एक का डुप्लिकेट के रूप में बंद कर दिया गया। मैं स्पष्टीकरण मांगूंगा।

+0

इस 'ALIGNOF()' संकेत के लिए बहुत बहुत धन्यवाद। – PiotrNycz

+0

हालांकि यह मैक्रो गैर-पीओडी प्रकारों के लिए काम नहीं करता है क्योंकि ऑफसेट जो गैर-पीओडी के साथ काम नहीं करता है (देखें http://stackoverflow.com/questions/1129894/why-cant-you-use-offsetof-on-non-pod-strucutures- इन-ग)। क्या आप मौके से गैर-पीओडी प्रकारों के समाधान को जानते हैं? – PiotrNycz

+0

क्या आप मेरे अपडेट पर टिप्पणी कर सकते हैं। ऐसा लगता है कि '__alignof __ (लंबा लंबा) == 8' सही है। और आपके 'एलीगॉफ़' के साथ 'स्ट्रक्चर' में बस 'लंबे समय तक' संरेखित करने के साथ क्या परीक्षण किया जाता है जो मेरे 'स्ट्रक्चर स्ल्ल {लंबे लंबे मीटर के समान होता है; } '। शायद आपकी बग रिपोर्ट के लिए यह मदद। – PiotrNycz

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