2012-07-08 27 views
33

आकार और संरेखण के बीच क्या अंतर है?आकार और संरेखण के बीच क्या अंतर है?

#include <iostream> 

#define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << '/' << alignof(T) << std::endl 

int main(int, char**) 
{ 
     SIZEOF_ALIGNOF(unsigned char); 
     SIZEOF_ALIGNOF(char); 
     SIZEOF_ALIGNOF(unsigned short int); 
     SIZEOF_ALIGNOF(short int); 
     SIZEOF_ALIGNOF(unsigned int); 
     SIZEOF_ALIGNOF(int); 
     SIZEOF_ALIGNOF(float); 
     SIZEOF_ALIGNOF(unsigned long int); 
     SIZEOF_ALIGNOF(long int); 
     SIZEOF_ALIGNOF(unsigned long long int); 
     SIZEOF_ALIGNOF(long long int); 
     SIZEOF_ALIGNOF(double); 
} 

इच्छा उत्पादन

1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 4/4 8/8 8/8 8/8

मुझे लगता है कि मुझे संरेखण क्या नहीं है ...?

+16

देशी प्रकारों के बजाय structs के साथ फिर से प्रयास करें। –

+1

'दिए गए प्रकार के किसी भी उदाहरण के लिए बाइट्स (दो की एक पूर्णांक शक्ति) में संरेखण देता है - http://en.cppreference.com/w/cpp/language/alignof। 'sizeof' बस आकार, बाइट्स में, निश्चित रूप से देता है। – chris

+1

शायद उल्लेख करने लायक है - [आकार हमेशा alignof का एक बहु है] (http://stackoverflow.com/questions/4637774/is-the-size-of-a-struct-required-to-be-an-exact-multiple -ऑफ-द-संरेखण-का-था) – Steve314

उत्तर

3

sizeof operator आपको वास्तविक प्रकार या किसी प्रकार के उदाहरण के बाइट्स में आकार देता है।

alignof operator आपको दिए गए प्रकार के किसी भी उदाहरण के लिए आवश्यक बाइट्स में संरेखण देता है।

+6

"संरेखण" क्या है? – user1494506

14

दो ऑपरेटर मौलिक रूप से अलग-अलग चीजें करते हैं। sizeof एक प्रकार का आकार देता है (यह कितनी मेमोरी लेता है) जबकि alignof देता है कि एक प्रकार को कितने बाइट्स को गठबंधन किया जाना चाहिए। ऐसा ही होता है कि आपके द्वारा परीक्षण किए गए प्राइमेटिव्स में उनके आकार के समान संरेखण आवश्यकता होती है (यदि आप इसके बारे में सोचते हैं तो यह समझ में आता है)।

क्या होता है अगर आप के बजाय एक struct है के बारे में सोचो:

struct Foo { 
    int a; 
    float b; 
    char c; 
}; 

alignof(Foo) वापस आ जाएगी 4.

+1

क्यों? 'alignof' क्या करता है? – user1494506

+1

@tskuzzy आपने कहा कि 'alignof (Foo)' वापस आ जाएगा 4. लेकिन यह लक्ष्य एबीआई के आधार पर है। तो यह ia32 (x86) पर सच हो सकता है लेकिन एआरएम, एमआईपीएस, पावरपीसी, आदि पर नहीं – ydroneaud

+3

4 ??? मुझे वास्तव में – Offirmo

54

ठीक है, "स्मृति" मूल रूप से बाइट्स की एक विशाल सरणी है। हालांकि, पूर्णांक जैसी अधिकांश बड़ी चीजें उन्हें स्टोर करने के लिए 1 से अधिक बाइट की आवश्यकता होती है - उदाहरण के लिए, 32 बिट मान, स्मृति के लगातार 4 बाइट्स का उपयोग करेगा।

अब, आपके कंप्यूटर में मेमोरी मॉड्यूल आमतौर पर "बाइट्स" नहीं होते हैं; वे कुछ बाइट्स "समांतर में" के साथ भी व्यवस्थित होते हैं, जैसे 4 बाइट्स के ब्लॉक।

memory byte 0 1 2 3  4 5 6 7  8 9 10 11 
integer  goooood 
        baaaaaaaaad 

यह वही "संरेखण" कहते है:

एक सीपीयू के लिए, यह बहुत आसान और अधिक कुशल = = नहीं "पार" इस ​​तरह के ब्लॉक-सीमाओं जब एक पूर्णांक की तरह कुछ पढ़ने के लिए बेहतर प्रदर्शन है एक 4 का संरेखण का अर्थ है कि इस प्रकार के डेटा को (या सीपीयू पर निर्भर करता है) को उस पते पर शुरू किया जाना चाहिए जो 4 से अधिक है।

आप अवलोकन करते हैं कि आकार == alignof गलत है; संरचनाओं का प्रयास करें। संरचनाओं को भी गठबंधन किया जाएगा (क्योंकि उनके व्यक्तिगत सदस्यों को सही पते पर समाप्त होने की आवश्यकता है), लेकिन उनका आकार बहुत बड़ा होगा।

+14

अतिरिक्त बिंदु नहीं समझा जाता है - हालांकि x86 अधिकतर चीजों के लिए अनियंत्रित पढ़ता है और लिखता है (धीरे-धीरे लेकिन सही ढंग से), कुछ आर्किटेक्चर को सभी परिचालनों को गठबंधन करने की आवश्यकता होती है, और यहां तक ​​कि x86 में कुछ विशेष मामले हैं जिन्हें गठबंधन किया जाना चाहिए (सिमड निर्देश, मुझे लगता है)। – Steve314

+0

धन्यवाद! अब मुझे यह – user1494506

+2

@ user1494506 मिल गया है - यदि यह या कोई अन्य उत्तर सही ढंग से आपके प्रश्न का उत्तर देता है, तो * इसे सही चिह्नित करने पर विचार करें। (बेशक यह * पूरी तरह से आपकी पसंद है *। जवाब स्वीकार करने के लिए मजबूर नहीं होना चाहिए क्योंकि लोग ऐसा कहते हैं (जैसे कि मैं अब कह रहा हूं) :) :) – ArjunShankar

5

संरेखण मूल्य मूल प्रकारों के आकार के मान के समान है।

अंतर परिभाषित डेटा प्रकारों जैसे संरचना का उपयोग करने में निहित है; उदाहरण के लिए

typedef struct { int a; double b; } S; 
//cout<<alignof(s);        outputp: 8; 
//cout<<sizeof(S);        output: 12; 

इसलिए आकार का मूल्य दिया गया डेटा प्रकार के लिए आवश्यक कुल आकार है; और alignof मान संरचना में सबसे बड़े तत्व की संरेखण आवश्यकता है।

संरेखण का उपयोग: किसी विशेष संरेखण सीमा पर स्मृति आवंटित करें।

6

पुराना प्रश्न (हालांकि उत्तर के रूप में चिह्नित नहीं किया गया ..) लेकिन सोचा कि यह उदाहरण ईसाई स्टीबर के उत्तर के अलावा अंतर को और अधिक स्पष्ट बनाता है। इसके अलावा Meluha का जवाब यह भी दर्शाता है कि इसके साथ आकार से सबसे अच्छा आदेश के सदस्यों के रूप में sizeof (एस) उत्पादन 16 नहीं 12.

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary 
//   | 8 bytes | | 8 bytes | | 8 bytes | 
struct Bad { char c;  double d;  int i;  }; 
cout << alignof(Bad) << " " << sizeof(Bad) << endl; // 8 24 

//    | 8 bytes | | 8 bytes |  
struct Good { double d;  int i; char c;   }; 
cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16 

है कोई त्रुटि है सबसे बड़ा पहले (इस मामले में डबल), दूसरों के सदस्य हैं के रूप में उस सदस्य द्वारा बाध्य

2

प्रदान किए गए उत्तरों के लिए, संरेखण वास्तव में क्या है इसके बारे में कुछ भ्रम लगता है। भ्रम शायद उत्पन्न होता है क्योंकि 2 प्रकार के संरेखण होते हैं।

1. सदस्य संरेखण

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

struct A 
{ 
    char c; float f; short s; 
}; 

struct B 
{ 
    float f; short s; char c; 
}; 

दोनों संरचनाओं में बिल्कुल वही जानकारी होती है। इस उदाहरण के लिए; फ्लोट प्रकार 4 बाइट लेता है, लघु प्रकार 2 लेता है और चरित्र 1 बाइट लेता है। हालांकि, पहली संरचना ए में यादृच्छिक क्रम में सदस्य हैं, जबकि दूसरी संरचना बी अपने बाइट आकार के अनुसार सदस्यों को आदेश देती है (यह कुछ आर्किटेक्चर पर अलग हो सकती है, मैं इस उदाहरण में 4-बाइट संरेखण के साथ x86 इंटेल CPU आर्किटेक्चर मान रहा हूं)।

printf("size of A: %d", sizeof (A)); // size of A: 12; 
printf("size of B: %d", sizeof (B)); // size of B: 8; 

आप आकार 7 बाइट्स होने की अपेक्षा करेंगे, तो आप यह सोचते हैं की जाएगी कि सदस्यों एक 1-बाइट संरेखण का उपयोग कर संरचना में पैक कर रहे हैं: अब संरचना का आकार पर विचार करें। हालांकि कुछ कंपाइलर्स इसे अनुमति देते हैं, आम तौर पर अधिकांश कंप्यूटर्स ऐतिहासिक कारणों से डी-वर्ड (डबल-वर्ड) या क्यूडब्ल्यूओआर (क्वाड-वर्ड) सामान्य प्रयोजन रजिस्ट्रार के साथ अधिकांश सीपीयू का काम 4-बाइट या 8-बाइट संरेखण का उपयोग करते हैं)।

पैकिंग प्राप्त करने के लिए काम पर 2 पैडिंग तंत्र हैं।

  1. सबसे पहले, प्रत्येक सदस्य है कि एक बाइट आकार बाइट-संरेखण अगले सदस्य (सदस्यों) यदि जिसके परिणामस्वरूप बाइट आकार छोटा या बाइट-संरेखण के बराबर है 'के साथ विलय कर दिया' है की तुलना में छोटे है। संरचना बी में, सदस्यों और सी को इस तरह से विलय किया जा सकता है; सी = 1 3 बाइट < = 4-बाइट संरेखण के लिए उनके संयुक्त आकार एस + 1 बाइट के लिए 2 बाइट्स हैं। संरचना ए के लिए, ऐसा कोई विलय नहीं हो सकता है, और प्रत्येक सदस्य प्रभावी रूप से संरचना के पैकिंग में 4 बाइट्स का उपभोग करता है।

  2. संरचना का कुल आकार फिर से गद्देदार है ताकि अगली संरचना संरेखण सीमा पर शुरू हो सके। उदाहरण में बी बाइट्स की कुल संख्या 7 होगी। अगली 4-बाइट सीमा बाइट 8 पर निहित है, इसलिए सरणी आवंटन को उदाहरणों के तंग अनुक्रम के रूप में अनुमति देने के लिए संरचना को 1 बाइट से जोड़ा जाता है।

ध्यान दें कि विजुअल C++/जीसीसी 1 बाइट, 2 बाइट्स के 2 और उच्च गुणकों के विभिन्न संरेखण अनुमति देते हैं।समझें कि यह आपके कंपाइलर के लिए इष्टतम कोड बनाने के लिए आपके कंपाइलर की क्षमता के विरुद्ध काम करता है। दरअसल, निम्नलिखित उदाहरण में, प्रत्येक बाइट को प्रत्येक पठन ऑपरेशन के लिए एकल-बाइट निर्देश का उपयोग करके एकल बाइट के रूप में पढ़ा जाएगा। प्रैक्टिस में, हार्डवेयर अभी भी पूरी मेमोरी लाइन लाएगा जिसमें प्रत्येक बाइट कैश में पढ़ा जाएगा, और निर्देश 4 बार निष्पादित करेगा, भले ही 4 बाइट एक ही डीडब्ल्यूओआर में बैठे हों और सीपीयू रजिस्टर में 1 निर्देश में लोड किया जा सके।

#pragma pack(push,1) 
struct Bad 
{ 
    char a,b,c,d; 
}; 
#pragma pack(pop) 

2. आबंटन संरेखण

यह बारीकी से 2 गद्दी तंत्र से संबंधित है पिछले अनुभाग में बताया गया है, तथापि, एक llocation संरेखणmalloc/memalloc के प्रकारों में निर्दिष्ट किया जा सकता आवंटन कार्यों। इसलिए, किसी ऑब्जेक्ट को संरचना/ऑब्जेक्ट प्रकार के बाइट-संरेखण सुझावों की तुलना में किसी ऑब्जेक्ट को आवंटित करना संभव है (आमतौर पर उच्चतम 2) संरेखण सीमा।

size_t blockAlignment = 4*1024; // 4K page block alignment 
void* block = malloc(sizeof(T) * count, blockAlignment); 

कोड प्रकार टी की गिनती उदाहरणों में से ब्लॉक पतों 4096.

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

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