2010-09-16 7 views
6

मुझे समझ नहीं आता क्योंदो शून्य पॉइंटर्स के साथ एक संरचना का आकार 4 है?

struct e{ 
    void * a; 
    void * b[]; 
} 

sizeof (ई) == 4 जबकि

struct f{ 
    void * a; 
    void * b; 
} 

है sizeof (च) == 8.

+0

एक [ "struct हैक" की वैधता की चर्चा में ANSI C] (http://stackoverflow.com/questions/3711233/)। "स्ट्रक्चर हैक" पर खोज करना तो अभी बहुत अधिक ब्याज नहीं लौटाता है, लेकिन वह वाक्यांश है जिसे आप ढूंढ रहे हैं। – dmckee

उत्तर

12

पहली संरचना में दूसरा पॉइंटर नहीं है, लेकिन एक एफएएम - लचीला सरणी सदस्य है। इसका उपयोग तब किया जाता है जब आपके पास एक लंबा बफर होता है और उस बफर की शुरुआत में e रखता है। इसके बाद आप शेष स्मृति को अनुक्रमित कर सकते हैं जो उस FAM का उपयोग करके e ऑब्जेक्ट का पालन करें और उस स्मृति को void* की सरणी के रूप में मानें।

स्टैंडर्ड कहते हैं (मेरे द्वारा जोर)

एक विशेष मामले के रूप में, एक से अधिक नामित सदस्य के साथ एक संरचना के अंतिम तत्व एक अधूरी सरणी प्रकार हो सकता है; इसे एक लचीला सरणी सदस्य कहा जाता है। ज्यादातर स्थितियों में, फ़्लैबल एक्स्टेबल सरणी सदस्य को अनदेखा किया जाता है। विशेष रूप से, संरचना का आकार ऐसा है जैसे लचीला सरणी सदस्य छोड़ा गया था, सिवाय इसके कि से अधिक पिछला पैडिंग हो सकता है, तो चूक का मतलब होगा।

उदाहरण के लिए, निम्न कोड आउटपुट के बिना struct के लिए 1, लेकिन जीसीसी पर परिवार के साथ struct के लिए 4, क्योंकि पहुँच पूर्णांकों के लिए परिवार की जरूरत ठीक से इस में एक 4 बाइट सीमा पर गठबंधन किया जाना (उदाहरण)

struct A { 
    char a; 
}; 

struct B { 
    char a; 
    int flex[]; 
}; 

int main() { 
    printf("sizeof A: %d\nsizeof B: %d\n", 
     (int)sizeof(struct A), 
     (int)sizeof(struct B) 
    ); 

    struct B *b = malloc(sizeof *b + sizeof(int[3])); 
    b->a = 'X'; 
    b->flex[0] = 1; 
    b->flex[1] = 2; 
    b->flex[2] = 3; 
    free(b); 
} 
+0

चूंकि आपने विभिन्न पदों में सामग्री संकलित की है और एक उदाहरण जोड़ा है, इसलिए मैंने पिछले उत्तर में आपका उत्तर स्वीकार कर लिया है। –

17
struct e{ 
    void * a; 
    void * b[]; 
//   ^^ 
} 

[] में है एक संरचना b एक सी 99 "लचीला सरणी सदस्य" बनाता है। इस प्रकार sizeof(e) केवल a के आकार, जो कि 4.

C99 § 6.7.2.1/16 से

माना जाएगा:

एक विशेष मामले के रूप में, एक से अधिक नामित सदस्य के साथ एक संरचना के अंतिम तत्व एक अपूर्ण सरणी प्रकार हो सकता है; इसे लचीला सरणी सदस्य कहा जाता है। ज्यादातर स्थितियों में, लचीला सरणी सदस्य को अनदेखा किया जाता है। विशेष रूप से, संरचना का आकार ऐसा लगता है जैसे लचीला सरणी सदस्य छोड़ दिया गया था, सिवाय इसके कि इसमें चूक से अधिक पीछे की पैडिंग हो सकती है।

हालांकि, जब . (या ->) ऑपरेटर के पास एक बाएं ऑपरेंड होता है जो एक लचीला सरणी सदस्य और सही ऑपरेंड नाम वाले एक संरचना के लिए एक सूचक होता है, तो यह व्यवहार करता है जैसे कि उस सदस्य को प्रतिस्थापित किया गया था सबसे लंबी सरणी (उसी तत्व प्रकार के साथ) जो ऑब्जेक्ट तक पहुंचने से संरचना को बड़ा नहीं बनायेगी; सरणी का ऑफ़सेट लचीला सरणी सदस्य का ही रहेगा, भले ही यह प्रतिस्थापन सरणी से भिन्न होगा। यदि इस सरणी में कोई तत्व नहीं होता है, तो यह व्यवहार करता है जैसे कि इसमें एक तत्व था लेकिन यदि उस तत्व तक पहुंचने के लिए कोई प्रयास किया गया है या एक पॉइंटर उत्पन्न करने के लिए व्यवहार किया गया है तो व्यवहार अपरिभाषित है।

+1

क्या इसका मतलब है कि मैं इसका उपयोग नहीं कर सकता? –

+0

@Alan: नहीं, आप अभी भी 'बी' तक पहुंच सकते हैं। – kennytm

+0

@Alan: नहीं; इसका मतलब यह है कि आकार() आपके द्वारा देखे जाने वाले परिणाम को लौटाता है। –

2

इसका कारण यह है दूसरा struct एक लचीला सदस्य सरणी का उपयोग करता है।आकार के परिणाम का स्पष्टीकरण Wikipedia में है।

1

void * b[];C89 में अमान्य है, तो इसका मतलब है कि आप C99 कंपाइलर का उपयोग कर रहे हैं। यह अब "लचीला सरणी सदस्य" और इससे पहले कि यह आवंटित किया जाता है स्मृति कहा जाता है, इसका आकार 0.

+0

यह भी ध्यान रखना महत्वपूर्ण था क्योंकि मैं C89 के साथ चिपकने की कोशिश कर रहा था। धन्यवाद! –

0

है पहले के लिए किसी भी स्थान की घोषणा नहीं कर रहा है क्योंकि:

C99 "struct हैक" को परिभाषित करने के लिए एक साधन की शुरुआत की "बी" में पॉइंटर्स।

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