2014-11-23 6 views
5

यह स्पष्ट है कि सी cannot insert padding between their elements में सरणी। हालांकि, क्या कोई नियम कह रहा है कि वे सरणी के अंत पर पिछली पैडिंग नहीं जोड़ सकते हैं?क्या किसी सरणी में पिछली पैडिंग हो सकती है?

यानी यह प्रोग्राम हर जगह एक ही परिणाम देने की गारंटी देता है?

#include <stdio.h> 
int main(void) { 
    typedef char a[3]; 
    typedef a b[3]; 
    printf("%zu %zu\n", sizeof(a), sizeof(b)); // -> 3 9 
} 

जहाँ तक मुझे, बाहर काम के रूप में कर सकते हैं a के आकार के पीछे बाइट या पांच जोड़ने, शायद एक गुमराह अनुकूलन करने की कोशिश में, सरणी का उपयोग नियमों को तोड़ने नहीं होगा (b[1][1] अभी भी परवाह किए बिना *(&b + sizeof(a) * 1 + 1) लिए वास्तव में नक्शे इसके आकार के a ऑब्जेक्ट्स के आकार में, और a की लंबाई से परे पहुंच यूबी है)।

मुझे सी मानक में कहीं भी नहीं मिल रहा है, जहां यह वास्तव में कहता है बिल्कुल सही है कि सरणी का आकार तत्व प्रकार की संख्या से गुणा तत्व प्रकार का आकार है। 6.5.3.4 केवल यह कहता है कि sizeof सरणी में "बाइट्स की संख्या" देता है (यह कोड उदाहरण के रूप में sizeof array/sizeof array[0] देता है, लेकिन यह केवल एक उदाहरण है - यह नहीं कहता कि इसे पर काम करना है, और यह नहीं है कोई विवरण दें)।

अंतर्निहित गारंटी पोर्टेबल कोड लिखने के लिए उपयोगी है जो सटीक डेटा लेआउट पर निर्भर करती है, उदा। गुजर पैक आरजीबी मान:

typedef uint8_t RGB[3]; 
RGB * data = ...; 
glColorPointer(3, GL_UNSIGNED_BYTE, 0, data); 

(ठीक तो ओपन कदम मान स्वीकार कर सकते हैं तो यह एक बुरा उदाहरण है, लेकिन आप समझ गए होंगे) उस मामले के लिए

, मैं बड़े पैमाने पर धारणा (यहां तक ​​कि करने के लिए से मान मानक में उदाहरण) कि आप sizeof के साथ सरणी के तत्वों की संख्या प्राप्त कर सकते हैं, यह किसी भी तरह से हर जगह सच होने की संभावना है - क्या कोई ज्ञात परिस्थितियां हैं जहां यह नहीं है?

+0

पैडिंग का अर्थ डेटा गठबंधन करना है। आपके मामले में, मुझे यकीन है कि 3 के सभी चार सरणी के आकार 3 होंगे। लेकिन यदि आप एक int के बाद घोषित करते हैं, तो 1 या 5 पैडिंग का पालन किया जा सकता है। एक अच्छा सी संकलक अतिरिक्त नौकरी नहीं करेगा जो भविष्यवाणी करना मुश्किल बनाता है। लेकिन यदि आप पोर्टेबिलिटी के बारे में बात कर रहे हैं, तो मुझे लगता है कि प्लेटफ़ॉर्म में बहुत अंतर होने पर लक्ष्य प्लेटफ़ॉर्म में कोड को फिर से संकलित करना या क्रॉस संकलन करना बेहतर है। – HuStmpHrrr

+0

"और यह कोई विवरण नहीं देता है" - यह कहता है कि सरणी में तत्वों की संख्या की गणना करता है। आप सही हैं कि यह केवल एक उदाहरण है, और यह उदाहरण मानक नहीं हैं। – hvd

+0

कोई अप्रत्यक्ष रूप से कटौती कर सकता है कि बाद के खंड को देखकर उस सरणी में ऐसे पैडिंग नहीं होते हैं: "जब ऑपरेशन पर लागू होता है जिसमें संरचना या संघ प्रकार होता है, तो परिणाम आंतरिक और पिछला समेत ऐसी वस्तु में बाइट्स की कुल संख्या है गद्दी।" - संरचनाओं और संघों में पैडिंग के लिए यह स्पष्ट संदर्भ, और सरणी के मामले में इसकी कमी मुझे विश्वास दिलाती है कि सरणी में ऐसे पैडिंग नहीं हो सकते हैं। –

उत्तर

6

मेरा मानना ​​है कि मानक के लिए वास्तव में यह आवश्यक नहीं माना जाता था कि सरणी में पैडिंग नहीं है, सरल कारण यह है कि इस तरह के पैडिंग किसी भी कार्यान्वयन पर कभी उपयोगी नहीं हो सकता है।

उसने कहा, मुझे विश्वास है कि == ऑपरेटर के विवरण के माध्यम से मानक इस तरह के पैडिंग को रोकता है।

6.5.9 समानता ऑपरेटरों

शब्दार्थ

6 दो संकेत की तुलना बराबर और केवल यदि [...] या एक एक सूचक के अंत पिछले एक करने के लिए है एक सरणी ऑब्जेक्ट और दूसरा एक अलग सरणी ऑब्जेक्ट की शुरुआत के लिए एक सूचक है जो तुरंत पता स्थान में पहली सरणी ऑब्जेक्ट का पालन करता है।

को देखते हुए

int array[2][2]; 

अभिव्यक्ति &array[0][2] अंक पहली सरणी subobject के अंत अतीत एक सूचक है। &array[1][0] दूसरे सरणी उपरोक्त के लिए एक सूचक है, जो तुरंत स्मृति में पहली सरणी का पालन करता है। इन पॉइंटर्स को बराबर तुलना करने की आवश्यकता है।यदि int[2] में पिछला पैडिंग था, तो sizeof(int[2]) > 2 * sizeof(int), मैं कल्पना नहीं कर सकता कि कोई भी कार्यान्वयन दो पॉइंटर्स को बराबर के रूप में कैसे तुलना कर सकता है।

+0

अच्छी तरह से देखा, +1। –

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

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