2009-09-14 10 views
6

मैंने कहीं पढ़ा है कि यदि आप एक सीआर/सी ++ फ़ंक्शन को एक वर्ण सरणी (जैसा कि std :: स्ट्रिंग के विपरीत) वापस करने के लिए चाहते हैं, तो आपको char * के बजाय कॉन्स्ट char * वापस करना होगा। उत्तरार्द्ध करने से प्रोग्राम क्रैश हो सकता है।वापसी प्रकार में क्रॉस चार * के बजाय char * का उपयोग क्यों कर सकते हैं क्रैश?

क्या कोई यह समझा सकता है कि यह सच है या नहीं? यदि यह सच है, तो एक समारोह से एक char * वापस इतना खतरनाक क्यों लौट रहा है? धन्यवाद।

const char * my_function() 
{ 
    .... 
} 

void main(void) 
{ 
    char x[] = my_function(); 
} 
+6

मुख्य() हमेशा int वापस करना चाहिए! http://users.aber.ac.uk/auj/voidmain.shtml – nmuntz

उत्तर

14

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

उदाहरण:

const char* errstr(int err) 
{ 
    switch(err) { 
     case 1: return "error 1"; 
     case 2: return "error 2"; 
     case 3: return "error 3"; 
     case 255: return "error 255 to make this sparse so people don't ask me why I didn't use an array of const char*"; 
     default: return "unknown error"; 
    } 
} 
+0

यह पूर्णता से भी ध्यान दिया जाना चाहिए कि ये इंटर्न किए गए हैं और अन्य चर समान स्थान पर इंगित कर सकते हैं। हालांकि, अगर कॉन्स्ट का सम्मान किया जाता है तो यह कोई समस्या नहीं होनी चाहिए। –

2

यदि char * स्टैक पर आवंटित किया गया है, तो आप एक लटकते सूचक को वापस कर देते हैं। अन्यथा, जब तक यह फ़ंक्शन के प्रोटोटाइप से मेल खाता है और घोषणा वापसी मूल्य से मेल खाती है, तो आपको ठीक होना चाहिए।

11

आपको जो बताया गया था वह सत्य नहीं है।

const char * लौटने से एक फ़ंक्शन के अर्थशास्त्र में सुधार हो सकता है (यानी जो मैं आपको दे रहा हूं उससे गड़बड़ न करें) लेकिन char * लौटाना बिल्कुल ठीक है।

हालांकि, या तो मामले में, आप सुनिश्चित करें कि आप एक char * या const char * कि my_function में ढेर पर आवंटित किया गया था (यानी malloc या new का उपयोग कर आवंटित), अन्यथा जब भी my_function रिटर्न के लिए स्मृति लौटने के लिए, करना चाहिए [const] char * को हटा दिया जाएगा, और आप एक अवैध सूचक का उपयोग करेंगे।

और अंत में आप free या delete[const] char * है कि आप करने के लिए एक बार आप इसे पूरा कर चुके हैं, या आप स्मृति रिसाव हो जाएगा लौटा दिया गया है करने के लिए याद रखना चाहिए। सी/सी ++ ऐसी महान भाषा नहीं हैं?

तो, सी में, आप

const char *my_function() { 
    const char *my_str = (const char *)malloc(MY_STR_LEN + 1); // +1 for null terminator. 
    /* ... */ 
    return my_str; 
} 

int main() { 
    const char *my_str = my_function(); 
    /* ... */ 
    free(my_str); 
    /* ... */ 
    return 0; 
} 
+1

इस तरह की बात यह है कि मुझे सी ++ की std :: स्ट्रिंग क्यों पसंद है (भले ही यह एक स्ट्रिंग क्लास परिभाषा का खराब हैक जॉब है), और स्मार्ट पॉइंटर्स । आपको केवल सी –

+0

@ डेविड थॉर्नले में बहुत अधिक दर्द से गुज़रना होगा, उचित दस्तावेज उस दर्द को लगभग शून्य तक कम कर देता है। – Qix

1

सीधे शब्दों में वापसी कोड को बदलने के लिए एक दुर्घटना का कारण नहीं होगा। हालांकि यदि आपके द्वारा वापस की जाने वाली स्ट्रिंग स्थिर है (उदाहरण के लिए return "AString"), तो आपको यह सुनिश्चित करने के लिए const char * वापस करना चाहिए कि संकलक उस स्मृति के किसी भी प्रयास में संशोधन का पता लगाता है, जो संभावित रूप से क्रैश का कारण बनता है। आप निश्चित रूप से कंपाइलर चेक के आसपास होने के लिए कास्ट और इस तरह का उपयोग कर सकते हैं, लेकिन उस स्थिति में आपको क्रैश होने के लिए कार्य करना होगा।

+0

धन्यवाद। क्या आप कह रहे हैं कि यदि आप एक शाब्दिक स्ट्रिंग लौटते हैं (उदा। "यह एक परीक्षण है";), वापसी का प्रकार const char * होना चाहिए? अगर वापसी का प्रकार char * है तो खतरे क्या है? – Andy

+0

यदि स्ट्रिंग संशोधित नहीं होती है, तो कोई खतरा नहीं होता है, लेकिन यदि कॉलर स्ट्रिंग को संशोधित करने का प्रयास करता है, तो एप्लिकेशन क्रैश हो जाएगा। यदि रिटर्न प्रकार 'const char *' है, तो संकलक आपको इसे संशोधित करने नहीं देगा। –

+0

धन्यवाद। शायद यही वह बात कर रहा है जिसके बारे में वे बात कर रहे हैं। सी के एक अन्य पहलू को नहीं पता था (और std :: स्ट्रिंग के लिए तीन चीयर्स बहुत अच्छा है!)। – Andy

4

आमतौर पर, यह कोई मुद्दा नहीं है, लेकिन विचार करने के लिए कुछ चीजें हैं। यह आम तौर पर कॉन्स-शुद्धता का मामला है, जिसका मतलब है कि आप क्या बदल सकते हैं और आप क्या नहीं कर सकते हैं इसका ट्रैक रखना।

यदि आप एक डबल-उद्धृत स्ट्रिंग लौट रहे हैं, तो यह const char * है, और इसे किसी और चीज की तरह परेशानी के लिए निमंत्रण है। ऐसी स्ट्रिंग को बदलना अपरिभाषित व्यवहार है, लेकिन आमतौर पर प्रोग्राम को उस स्ट्रिंग को क्रैश या बदलने का कारण बनता है जहां इसे संदर्भित किया जाता है।

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

यदि कॉल किया गया फ़ंक्शन कुछ ऐसा लौटा रहा है जो पहले से ही const char * है, तो इसे char * पर बदलना एक कलाकार की आवश्यकता है। इसके अलावा, यदि आप वास्तव में इसे बदलने जा रहे हैं, तो आपको यह सुनिश्चित करना होगा कि यह परिवर्तनीय है। इसे const char * के रूप में रखना आमतौर पर बेहतर होता है।

malloc() या new साथ आबंटित स्मृति लौटने के साथ तत्काल कोई समस्या नहीं है, लेकिन आप स्वामित्व की समस्या है: क्या समारोह free()/delete यह, कब, और क्या आप संभव प्रतियां के बारे में क्या करते हो जाना चाहिए? यह वह जगह है जहां सी ++ के स्मार्ट पॉइंटर्स चमकते हैं।

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

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