2009-11-04 9 views
11

जैसा कि मुझे पता है, सी में समय संकलित करने से पहले एक सरणी को एक विशिष्ट आकार की आवश्यकता होती है।सी में आकार चलाने पर सरणी का आकार निर्धारित किया जा सकता है?

मुझे आश्चर्य है कि यह कोड अभी भी क्यों काम करता है?

int s; 
printf("enter the array size: "); 
scanf("%d",&s); 

int a[s]; // Isn't s value determined at run time? 

उत्तर

19

सरणी आकार एएनएसआई 89 सी 99 कल्पना इस सीमा को हटा दिया के संस्करण के साथ जाना जाता है और चर सरणियों आकार के लिए अनुमति दी जानी चाहिए।

यहाँ प्रलेखन कोई इस सुविधा

+0

ओह मैं देखता हूं। धन्यवाद। तो सरणी के सभी तत्व अभी भी ढेर पर स्थित हैं? – root

+0

हां, वे हैं। यदि यह बुरा है, तो अन्य उत्तरों में सुझाए गए अनुसार मॉलोक का उपयोग करें। –

4

आप गतिशील आकार के साथ एक सरणी आवंटित करने के लिए की जरूरत है, तो आप ढेर से इसे पाने के लिए, malloc के साथ() की है।

int *a = (int*)malloc(sizeof(int) * s) 
+2

यदि आप '(int *) 'कास्ट ड्रॉप करते हैं, तो संकलक एक त्रुटि उत्पन्न करेगा यदि आप' malloc' परिभाषित फ़ाइल को शामिल करना भूल गए हैं। इस प्रकार यह सबसे अच्छा अभ्यास है कि कलाकार शामिल न करें। –

+1

'int * a = malloc (s * sizeof * a)' – AnT

0

आप दो बातें यहाँ भ्रमित कर रहे हैं की जीएनयू संस्करण है।

1)() एक पहले से ही आवंटित सरणी के आकार जो अपने शीर्षक का तात्पर्य निर्धारण:

sizeof(a)/sizeof(a[0]) 

2) गतिशील रूप से आवंटित: (जैसे कि, पहले) तत्व एक के आकार से कुल के लिए विभाजन sizeof() स्मृति आपके प्रश्न के रूप में पूछता है:

int *a = (int*)malloc(s * sizeof(int)); 
+0

आकार (ए)/आकार (एक [0]) संकलन-समय पर एक सरणी का आकार निर्धारित करता है, रन-टाइम नहीं, अगर इसे सरणी घोषणा की तरह ढेर पर आवंटित किया जाता है। –

1

यह कोड C99 भाषा विनिर्देश द्वारा समर्थित है। यह कोड एक विस्तार के रूप में सी 8 9/9 0 मोड में जीसीसी कंपाइलर द्वारा भी समर्थित है।

तो, आपके प्रश्न का उत्तर (यह "काम करता है") इस बात पर निर्भर करता है कि आप इसे कैसे संकलित कर रहे हैं। सामान्य स्थिति में, यह एक C89/90 कंपाइलर द्वारा भी संकलित नहीं होगा।

0

यह समझना महत्वपूर्ण है कि आपके प्रश्न के उचित उत्तर देने के लिए एक कंपाइलर द्वारा चर को कैसे आवंटित किया जाता है। दो मोड हैं जिनमें मेमोरी को आवंटित किया जाता है, यह एक ढेर पर हो सकता है या यह एक ढेर पर हो सकता है। एक ढेर पर मेमोरी गतिशील आवंटित किया जाता है। तो एक चर जो एक ढेर पर स्मृति आवंटित किया जाता है उसे रन टाइम के दौरान अपना आकार दिया जा सकता है।

सी के मामले में सरणी को ढेर पर स्मृति दी जाती है। एक ढेर पर स्मृति प्रदान करने के लिए स्मृति के आकार को संकलन समय के दौरान संकलक को जाना जाना चाहिए। ताकि रन टाइम के दौरान स्टैक पर चर के लिए बहुत मेमोरी सेट की जा सके। यही कारण है कि आप सी भाषा के संबंध में रन टाइम पर सरणी के आकार का निर्णय नहीं ले सकते हैं।

+1

स्टैक पर स्मृति आवंटित करना केवल स्टैक पॉइंटर को समायोजित करने का मामला है - और वहां कोई * मौलिक कारण नहीं है कि स्टैक पॉइंटर केवल संकलन समय पर ज्ञात मानों द्वारा समायोजित किया जा सकता है। दरअसल, सबसे हालिया सी मानक स्वचालित वैरिएबल को अनुमति देता है जिसका आकार रनटाइम पर निर्धारित होता है, और वहां एक सामान्य एक्सटेंशन 'एलोका()' भी होता है जो * * * से पहले के लिए एक ही चीज़ प्रदान करता है। – caf

0

Variable Length ArraysC99 से सी भाषा का हिस्सा रहा है। लेकिन उन्हें C11 में एक विशेषता के रूप में बनाया गया है - जिसका अर्थ है कि एक सी 11 अनुरूप कार्यान्वयन की आवश्यकता नहीं है (हालांकि, व्यावहारिक रूप से सभी कार्यान्वयन जो सी 99 का समर्थन करते हैं निश्चित रूप से सी 11 में वीएलए प्रदान करते हैं)।

आप जांच सकते हैं कि क्या आप कार्यान्वयन मैक्रो __STDC_NO_VLA__ (यदि इसे संकलन के सी 99 या सी 11 मोड में परिभाषित किया गया है) का उपयोग करके वीएलए प्रदान नहीं करता है, तो आपका कार्यान्वयन वीएलए का समर्थन नहीं करता है)।

तो रनटाइम पर एक सरणी आकार तय करने आधुनिक सी (> = C99) और कोड नीचे की तरह में संभव है ठीक है:

int s; 
printf("Enter the array size: "); 
scanf("%d", &s); 
int a[s]; 

Vlas में से एक स्पष्ट दोष यह है कि s काफी बड़ा है और अगर a का आवंटन विफल हो गया। इससे भी बदतर, यह जांचने का कोई तरीका नहीं है कि आवंटन विफल हो गया है और आप रनटाइम त्रुटियों (उदा।, Segfault) में भाग लेंगे। यह अनिवार्य रूप से undefined behaviour है। तो यदि आप सरणी आकार बहुत बड़ा है तो आप वीएलए से बचना चाहते हैं। असल में, जब संदेह में, गतिशील स्मृति आवंटन के लिए जाएं (नीचे देखें)।

वीएलए के साथ अन्य की तुलना में बहुत कम गंभीर, यह है कि उनके पास स्वचालित संग्रहण अवधि (उर्फ "आवंटित स्टैक आवंटित") है। तो यदि आप ऐसा कुछ चाहते हैं जो लंबी अवधि तक रहता है तो ब्लॉक स्कोप जहां वीएलए घोषित किया गया है, तो वीएलए की कोई मदद नहीं है।

C89 में, कोई वीएलए नहीं है। तो गतिशील स्मृति आवंटन का उपयोग एकमात्र तरीका है। हालांकि, कुछ गैर-मानक एक्सटेंशन जैसे alloca() थे जो वीएलए के समान हैं और वीएलए के समान ही दोष हैं)।

int s; 
printf("enter the array size: "); 
scanf("%d",&s); 
int *a = malloc(s * sizeof *a); 
... 
free(a); 
संबंधित मुद्दे