2011-02-10 16 views
5
#include <stdio.h> 
#include <stdlib.h> 
typedef struct { 
    unsigned length; 
} List; 
void init(List *l) { 
    l = (List *) malloc(sizeof(List)); 
    l->length = 3; 
} 
int main(void) { 
    List *list = NULL; 
    init(list); 
    if(list != NULL) { 
     printf("length final %d \n", list->length); 
     return 0; 
    } 
    return 1; 
} 

यह कोड का एक सरलीकृत संस्करण है जो मुझे समस्याएं दे रहा है। मैं एक विधि से पॉइंटर *list बनाने की कोशिश कर रहा हूं जहां *list पैरामीटर के रूप में पारित किया गया है।सी - एक तर्क के रूप में पारित सूचक को

मुझे पता है कि मैं void init(List *l) इसे void init(List **l) पर बदलकर काम कर सकता हूं लेकिन यह एक क्लास ट्यूटोरियल के लिए है। मैं विधि तर्क नहीं बदल सकता। मैंने इस पर काम करने में चार घंटे बिताए हैं।

मैं यह सुनिश्चित करना चाहता हूं कि मेरे प्रोफेसर का सामना करने से पहले void init(List *l) कार्य करने का कोई तरीका नहीं है।

अग्रिम

उत्तर

4

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

void init(List **l) { 
    *l = (List *) malloc(sizeof(List)); 
    (*l)->length = 3; 
} 

init(&list); 

असाइनमेंट निर्दिष्ट है कि आप init के भीतर से List आवंटित करने के लिए है? यदि नहीं, तो आप हमेशा एक पहले से ही आवंटित List वस्तु के लिए एक सूचक गुजारें सकता है, और प्रदर्शन जो कुछ भी प्रारंभ length = 3 के लिए एक जगह धारक है:

void init(List *l) { 
    l->length = 3; 
} 

List list; 
init(&list); 
printf("length final %d \n", list.length); 
+1

पीओ विशेष रूप से उल्लेख किया गया है कि इसे "शून्य इनिट (सूची ** एल)" –

+0

@ गुनर से संबोधित किया जा सकता है – meagar

+0

असाइनमेंट निर्दिष्ट करता है कि यह कन्स्ट्रक्टर होना चाहिए। मैं अपने प्रोफेसर को ईमेल करने जा रहा हूं और उसे आवश्यकताओं को बदलने के लिए कहूंगा। आपकी सहायताके लिए धन्यवाद! –

3

समस्या यह है कि सूचक, मूल्य द्वारा पारित हो जाता है तो आप कर रहे हैं है परिवर्तनों को त्याग दिया जाता है। इसे सही तरीके से करने के लिए आपको वास्तव में एक पॉइंटर की आवश्यकता होती है। में के रूप में आप क्या करेंगे:

void init(List** l) { 
    *l = (List*) malloc(sizeof(List)); 
    // ... 
} 

और जब आप यह कहते हैं, आप init(&list) बजाय init(list) का प्रयोग करेंगे। बेशक, इस मामले में, यह समझ में आता है बस आगे बढ़ो और परिणाम लौटने एक सूचक के सूचक के उपयोग करने के बजाय करने के लिए:

List* init() { 
    List* result = (List *) malloc(sizeof(List)); 
    result->length = 3; 
    return result; 
} 

और फिर, इसके बाद के संस्करण के साथ, आप बस list = init(); इस्तेमाल कर सकते हैं।

ध्यान दें कि सी ++ में, आप पॉइंटर्स के बजाय संदर्भों का उपयोग कर सकते हैं, लेकिन संदर्भ और पॉइंटर्स मिश्रण अविश्वसनीय रूप से गन्दा है। यहां, रिटर्न-टाइप का उपयोग करना वास्तव में सबसे अच्छी बात है।

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

1

यह असाइनमेंट शायद क्लास द्वारा मूल्य के अनुसार पास करने और संदर्भ द्वारा पास करने का एक अच्छा तरीका है। यदि आप निर्माता के हस्ताक्षर को बनाए रखना चाहते हैं तो आपको मुख्य फ़ंक्शन को संशोधित करने की आवश्यकता है।

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
typedef struct { 
    unsigned length; 
} List; 


void init(List *l) { 
    l->length = 3; 
} 
int main(void) { 
    List list;// x = NULL; 
    memset(&list,0,sizeof(List)); 
    init(&list); 
    printf("length final %d \n", list.length); 
    return 1; 
} 

अब यहां सूची सूची है और सूची में पता नहीं है। init() विधि सूची के पते और अंदरूनी अंदर पारित आप संरचना सामग्री के मूल्य को बदल सकते हैं।

./a.out

लंबाई अंतिम 3

+0

मुझे लगता है कि मेमसेट encapsulation का उल्लंघन होने के लिए। सूची की सामग्री को init करने के लिए init जिम्मेदार है; अगर एक मेमसेट की आवश्यकता है, तो इसे करना चाहिए। जैसा कि है, इसकी आवश्यकता नहीं है। –

0

init एक मौजूदा सूची के लिए सूचक पारित किया जाना चाहिए। मुझे संदेह है कि यहां वास्तविक समस्या आपकी डेटा संरचना के साथ है। आपके पास एक सूची कहा जाता है, जिसमें लंबाई होती है, लेकिन कहीं भी देखने की कोई सूची नहीं है। सूची में दी गई लंबाई की सरणी में एक सूचक होना चाहिए, और init उस सरणी को malloc चाहिए और सूचक सेट करना चाहिए। जब आप प्रोफेसर से अपनी आवश्यकताओं को सही करने के लिए पूछेंगे तो आप शायद यह पता लगाएंगे कि अगर वे थे, तो शायद वे पिछले छात्रों से इसके बारे में सुना होगा और अब तक उन्हें सही करेंगे।

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