2012-12-23 8 views
5

SO पर समान प्रश्न हो सकता है। लेकिन, मुझे नहीं मिला था कि, यहाँ परिदृश्यसरणी पर malloc का उपयोग कर

प्रकरण 1

void main() 
{ 
    char g[10]; 
    char a[10]; 
    scanf("%[^\n] %[^\n]",a,g); 
    swap(a,g); 
    printf("%s %s",a,g); 
} 

प्रकरण 2

void main() 
{ 
    char *g=malloc(sizeof(char)*10); 
    char *a=malloc(sizeof(char)*10); 
    scanf("%[^\n] %[^\n]",a,g); 
    swap(a,g); 
    printf("%s %s",a,g); 
} 

मैं दोनों मामले में एक ही उत्पादन हो रही है है। तो, मेरा सवाल यह है कि मुझे malloc()array या उप-कविता के बजाय कब और क्यों चाहिए ?? मुझे सामान्य परिभाषा मिली, malloc() गतिशील आवंटन प्रदान करता है। तो, यह उनके बीच एकमात्र अंतर है ?? उदाहरण के साथ किसी को भी समझाएं, dynamic का अर्थ क्या है, हालांकि हम malloc() में आकार निर्दिष्ट कर रहे हैं।

+2

'sizeof char' हमेशा' 1' FYI –

उत्तर

6

सिद्धांत अंतर यह बताता है कि आप सरणी की लंबाई कब और कैसे तय करते हैं। निश्चित लंबाई सरणी का उपयोग करके आप संकलन समय पर अपनी सरणी लंबाई तय कर सकते हैं। इसके विपरीत malloc का उपयोग करके आप रनटाइम पर सरणी की लंबाई तय कर सकते हैं।

विशेष रूप से, रनटाइम पर निर्णय लेने से आप उपयोगकर्ता इनपुट पर निर्णय का आधार तय कर सकते हैं, उस समय जानकारी जो आप संकलित करते समय ज्ञात नहीं है। उदाहरण के लिए, आप उपयोगकर्ता द्वारा वास्तविक डेटा इनपुट को फिट करने के लिए पर्याप्त आकार के लिए सरणी आवंटित कर सकते हैं। यदि आप निश्चित लंबाई सरणी का उपयोग करते हैं, तो आपको ऊपरी बाध्य समय संकलित करने का निर्णय लेना होगा, और उसके बाद उस सीमा को उपयोगकर्ता पर मजबूर करना होगा।

एक और अधिक सूक्ष्म मुद्दा यह है कि स्थानीय चर के रूप में बहुत बड़ी निश्चित लंबाई सारणी आवंटित करने से ओवरफ्लो रनटाइम त्रुटियों का सामना हो सकता है। और इसी कारण से, आप कभी-कभी malloc का उपयोग करके गतिशील रूप से ऐसे एरे आवंटित करना पसंद करते हैं।

+0

मैं सराहना करता हूं, अगर आप कुछ उदाहरणों के साथ समझाएंगे – Ravi

+1

@var___ मेरा उत्तर देखें (और इसे समझने के प्रयास को करने का प्रयास करें, यह कुछ बुनियादी है ...) –

+0

हां, मैं कोशिश कर रहा हूं, एक बात, जिसने मुझे हर समय भ्रमित किया, शब्द 'गतिशील'। शायद, मैं आपके उत्तर से पता लगाने की कोशिश कर रहा हूं। – Ravi

2

कृपया कोई भी उदाहरण के साथ समझाएं, गतिशीलता का अर्थ क्या है हालांकि हम आकार निर्दिष्ट कर रहे हैं।

मुझे संदेह है कि यह सी 99 से पहले महत्वपूर्ण था। C99 से पहले, आप गतिशील रूप से आकार ऑटो सरणियों नहीं कर सकता:

void somefunc(size_t sz) 
{ 
    char buf[sz]; 
} 

वैध C99 लेकिन अवैध C89 है। हालांकि, malloc() का उपयोग करके, आप कोई मान निर्दिष्ट कर सकते हैं, आपको malloc() को निरंतर इसके तर्क के रूप में कॉल करने की आवश्यकता नहीं है।

इसके अलावा, स्पष्ट करने के लिए क्या अन्य उद्देश्य के malloc() है: यदि आप एक समारोह से ढेर-आबंटित स्मृति वापस नहीं लौट सकते, इसलिए यदि आपके समारोह आबंटित स्मृति वापस जाने के लिए की जरूरत है, आप आमतौर पर malloc() (या malloc के कुछ अन्य सदस्य का उपयोग स्मृति का एक ब्लॉक प्राप्त करने के लिए realloc() और calloc() सहित familiy)। यह समझने के लिए, निम्नलिखित कोड पर विचार करें:

char *foo() 
{ 
    char buf[13] = "Hello world!"; 
    return buf; 
} 

buf के बाद से, एक स्थानीय चर रहा है यह इसका आवरण समारोह के अंत में अवैध है - लौटने यह अनिर्धारित व्यवहार का परिणाम है। ऊपर दिया गया कार्य गलत है। हालांकि, एक सूचक malloc() का उपयोग कर प्राप्त समारोह कॉल के माध्यम से वैध रहता है (जब तक आप इसे पर free() कॉल नहीं करते):

char *bar() 
{ 
    char *buf = malloc(13); 
    strcpy(buf, "Hello World!"); 
    return buf; 
} 

यह बिल्कुल वैध है।

0

मैं जोड़ता हूं कि इस विशेष उदाहरण में, malloc() बहुत अपमानजनक है, क्योंकि सरणी के लिए आवंटित अधिक स्मृति है [मॉलोक में ओवरहेड के कारण] साथ ही साथ मॉलोक को कॉल करने के लिए जितना समय लगता है() और बाद में मुफ्त() - और प्रोग्रामर के लिए इसे मुक्त करने के लिए ओवरहेड है - मेमोरी लीक डीबग करने के लिए काफी कठिन हो सकता है।

संपादित करें: बिंदु में, आपका कोड मुख्य() के अंत में मुफ्त() गायब है (यहां कोई फर्क नहीं पड़ता है, लेकिन यह मेरे बिंदु को काफी अच्छी तरह से दिखाता है।

तो छोटे ढांचे (100 बाइट से कम) को आम तौर पर ढेर पर आवंटित किया जाना चाहिए। यदि आपके पास बड़ी डेटा संरचनाएं हैं, तो उन्हें मॉलोक के साथ आवंटित करना बेहतर होगा (या, यदि यह सही काम है, तो ग्लोबल्स का उपयोग करें - लेकिन यह एक संवेदनशील विषय है)।

स्पष्ट रूप से, यदि आप पहले से कुछ के आकार को नहीं जानते हैं, और यह बहुत बड़ा हो सकता है (आकार में किलोबाइट), यह निश्चित रूप से "मॉलोक का उपयोग करने पर विचार करें" का मामला है।

दूसरी तरफ, ढेर इन दिनों (कम से कम "असली कंप्यूटर" के लिए बहुत बड़े हैं), तो कुछ किलोबाइट्स स्टैक आवंटित करना एक बड़ा सौदा नहीं है।

+0

यह सलाह तब तक ठीक है जब आप संकलित समय पर कितनी मेमोरी की आवश्यकता होती है –

+0

हां, या कम से कम आप जानते हैं कि "यह इससे अधिक नहीं होगा, और जांचें कि यह और नहीं है"। जब भी आप इनपुट के आकार को नहीं जानते हैं, तो "मॉलोक का उपयोग करें" के सामान्य सुझाव को मैं नापसंद करता हूं - फ़ाइल नाम इनपुट करने के लिए 1000 वर्ण बफर रखने के लिए यह बिल्कुल ठीक है, आपको getchar द्वारा फ़ाइल नाम पढ़ने की आवश्यकता नहीं है और जैसा कि आप यह सुनिश्चित करने के लिए जाते हैं कि यह सही ढंग से मेल खाता है ... –

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