2016-01-14 13 views
6

मैं हमेशा इस्तेमाल किया सी में स्थिर से परिभाषित सरणियों से अधिक पुनरावृत्ति के लिए प्रतिमान निम्नलिखित गया है में गिनती:सरणी तत्व सी

struct foo { ... }; 
struct foo array[10]; 

for (int i; i < sizeof(array)/sizeof(array[0]); i++) 
    ... 

और, ठीक है, यह हर बार काम किया अब तक ;-)

लेकिन यह, आश्चर्य बनाता है यह अगर struct लंबाई है कि स्वाभाविक रूप से संरेखित नहीं करता है, जैसे की वास्तव में था नहीं तोड़ सकता है:

struct foo { long a; char b; }; 

नहीं संकलक का निर्णय लेते हैं कि sizeof(struct foo) == 7 जबकिसंरेखण (एलपी 64 डेटा मॉडल) के कारण?

+0

यदि मेरी धारणा सच थी या काउंटर-उदाहरण है तो मेरी कैप्चर हमेशा नहीं होती है, तो मैं एक कैननिकल संदर्भ की तलाश में हूं। –

+1

बीटीडब्ल्यू एक पूर्णांक विभाजन है, यह आपको गलत संख्या नहीं दे सका। क्या मै गलत हु? – LPs

+0

"कंपाइलर यह तय नहीं करेगा कि 'sizeof (struct foo) == 7'_" जरूरी नहीं है, पैडिंग हो सकती है। – emlai

उत्तर

5

sizeof ऑपरेटर के बारे में C99 standard, section 6.5.3.4 राज्यों के रूप में:

जब एक संकार्य सरणी प्रकार है कि करने के लिए लागू है, परिणाम सरणी में बाइट की कुल संख्या है।

और:

उदाहरण 2 sizeof ऑपरेटर का एक और उपयोग एक सरणी में तत्वों की संख्या गणना करने के लिए है:

 `sizeof array/sizeof array[0]` 

तो सरणी के आकार होगा हमेशा इसके तत्वों के आकार का एक बहु हो।

और structs के बारे में एक ही पैराग्राफ से:

जब एक संकार्य है कि संरचना या संघ प्रकार के लिए लागू किया, परिणाम, इस तरह के एक वस्तु में बाइट की कुल संख्या है आंतरिक और अनुगामी गद्दी सहित ।

+1

मानक से भी: "जब ऑपरेशन पर लागू होता है जिसमें संरचना या यूनियन प्रकार होता है, तो परिणाम इस तरह के ऑब्जेक्ट में बाइट्स की कुल संख्या है, ** आंतरिक और पीछे की पैडिंग सहित ** **" – dbush

+1

@dbush इसे जोड़ देगा जवाब अगर आपको कोई फर्क नहीं पड़ता .. –

4

सं।

किसी सरणी में कोई "मृत स्थान" नहीं है; यदि पैडिंग है, तो मेंstruct आकार में शामिल है।

+0

ऐसा लगता है कि आप पैसे पर सही हैं, मैं जीसीसी के '__attribute __ ((पैक)) के साथ संरचना आकार को बदल सकता हूं और उदा। '__attribute __ ((गठबंधन (128))) 'लेकिन जो भी मैं सरणी में करने की कोशिश करता हूं, यह सरणी का एक बहुतायत रहता है। –

1

sizeof मैक्रो के आकार को समस्त पैडिंग सहित आकार देता है। यह struct की स्थिर रूप से परिभाषित सरणी के लिए सच है। तो बयान:

sizeof(struct array)/sizeof(struct array[0]) 

हमेशा आप प्रत्येक struct तत्व में कितने या सदस्यों के लिए किस प्रकार की परवाह किए बिना सरणी तत्वों के माध्यम से पुनरावृति करने की अनुमति देगा।

पैकिंग/संरेखण सरणी सीमा
के लिए कोई फर्क नहीं यहां तक ​​कि अगर pragma pack निर्देश अपने स्रोत में प्रयोग किया जाता है, संभवतः के कारण (जो भी संरेखण को प्रभावित कर सकते हैं) पैकिंग बदलने के लिए, एक अलग मूल्य में जिसके परिणामस्वरूप बनाता है आपके सरणी के प्रत्येक संरचना तत्व के लिए आकार के लिए, सरणी तत्वों की गणना उसी पर निर्भर करती है।

... या एक जवाबी उदाहरण है अगर मेरी धारणा हमेशा

नहीं रखता है यह नोट करना महत्वपूर्ण है:
sizeof ऑपरेटर सरणियों struct के पर अलग काम करती है (या किसी भी अन्य प्रकार) जो वास्तव में ढेर पर गतिशील रूप से बनाए गए पॉइंटर्स हैं। उदाहरण के लिए यदि आप था:

typedef struct { ... }FOO; 
FOO *foo; 
... 
foo = malloc(10*sizeof(FOO)); 
size_t size = sizeof(foo); //returns sizeof pointer, (4 bytes on 32 bit target) 
          //No matter how many, or what type members make up the struct 

इसलिए

sizeof(struct foo)/sizeof(struct foo[0]) 

अब आप सरणी तत्वों की सही गिनती देंगे।

2

सदस्यों की संरचना इंटिनल संरेखण उस संरचना के सर पर प्रभाव नहीं डालता है। तो चाहे कोई भी सदस्य किस संरचना में शामिल है या वे कैसे गठबंधन किए गए हैं, आपके पास काम करने की गारंटी है।

हैं वहाँ struct के सदस्यों के बीच एक गद्दी है, तो यह सभी struct सरणी के तत्वों के लिए ही है। sizeof(array) हमेशा sizeof(array[0]) द्वारा समान रूप से विभाजित है।

तो सरणी आकार की गणना की विधि,

size_t len = sizeof(array)/sizeof(array[0]); 

रूप में लंबे समय array एक सरणी रूप किसी भी प्रकार के लिए काम करने के लिए गारंटी है।

1

कंपाइलर सदस्यों के बीच हर जगह संरचना के भीतर पैडिंग डालने के लिए स्वतंत्र है और इसके अंत में, अपवाद के साथ कि पहले सदस्य के ऑफसेट को हमेशा शून्य होना चाहिए।

दूसरी तरफ, Arrays तत्वों के बीच किसी भी "अंतराल" के बिना हमेशा संगत होना पड़ता है। मानक कहा गया है कि:

एक सरणी प्रकार वस्तुओं

आमतौर पर के समीप आवंटित अरिक्त समुच्च्य का वर्णन करता है, सबसे compilers सुनिश्चित करने के लिए struct के अंत में कुछ गद्दी से जोड़ दिया जाएगा कि जब समीपवर्ती बाहर रखी एक सरणी में, दूसरा तत्व कुछ सदस्यों की संरेखण आवश्यकताओं को तोड़ता नहीं है। सामान्य नियम यह है कि संरचना का कुल आकार उस आकार तक बढ़ाया जाना चाहिए जो सदस्य के संरेखण द्वारा सबसे बड़ी संरेखण आवश्यकता के साथ समान रूप से विभाजित है।

एक LP64 मॉडल में, sizeof(long) 8 और sizeof(char), 1. long 8-बाइट संरेखण की आवश्यकता होगी है char कोई संरेखण आवश्यकताएं होती हैं। आकारों का योग 9 होगा, लेकिन संकलक संरचना के आकार को 16 तक बढ़ाएगा, ताकि 16 % 8 == 0 हो।इस तरह, एक आसन्न सरणी तत्व उस स्थान पर शुरू होगा जो 8 द्वारा समान रूप से विभाजित है, इसलिए पहले सदस्य का संरेखण संरक्षित किया जाएगा।

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