सी

2012-04-02 31 views
68

में स्ट्रिंग शाब्दिक का "जीवनकाल" निम्नलिखित कार्य से वापस आने वाले सूचक को वापस नहीं पहुंच पाएगा?सी

char *foo(int rc) 
{ 
    switch (rc) 
    { 
     case 1:   return("one"); 
     case 2:   return("two"); 
     default:   return("whatever"); 
    } 
} 

तो C/C++ में एक स्थानीय चर के जीवनकाल व्यावहारिक रूप से केवल समारोह के भीतर, सही है? जिसका अर्थ है, char* foo(int) समाप्त होने के बाद, पॉइंटर जो लौटाता है उसका मतलब अब कुछ भी नहीं है?

मैं स्थानीय var के जीवनकाल के बारे में थोड़ा उलझन में हूं। क्या कोई मुझे एक अच्छा स्पष्टीकरण दे सकता है?

+9

आपके फ़ंक्शन में केवल "var" पैरामीटर 'int rc' है। इसका जीवनकाल 'रिटर्न' में से प्रत्येक पर समाप्त होता है। जिन पॉइंटर्स आप लौट रहे हैं वे स्ट्रिंग स्ट्रिंग हैं। स्ट्रिंग अक्षर में स्थिर भंडारण अवधि होती है: उनका जीवनकाल कम से कम कार्यक्रम के जितना होता है। – Kaz

+0

क्या होगा यदि यह स्ट्रिंग शब्दशः लेकिन अन्य प्रकार के शाब्दिक नहीं है, जैसे: int * foo() {वापसी &(2); // या // int n = 2; // वापसी और एन; } –

+0

मेरे उत्तर में संपादित करें जो आपकी क्वेरी को संबोधित करता है। ध्यान दें, आपको इसे एक टिप्पणी के रूप में पोस्ट करना चाहिए था और जवाब नहीं देना चाहिए। प्रश्नों, संदेह आदि को टिप्पणियों में पोस्ट किया जाना चाहिए, केवल उत्तरों को उत्तर के तहत पोस्ट किया जाना चाहिए। –

उत्तर

75

हां, स्थानीय चर का जीवनकाल दायरे के भीतर है ({, }) जिसमें यह बनाया गया है।
स्थानीय चर के स्वचालित या स्थानीय भंडारण होते हैं।
स्वचालित क्योंकि वे उस स्कोप के भीतर स्वचालित रूप से नष्ट हो जाते हैं, जिसमें वे बनाए जाते हैं।

हालांकि, आपके पास यहां एक स्ट्रिंग शाब्दिक है, जिसे एक कार्यान्वयन में आवंटित किया गया है जिसे केवल स्मृति पढ़ा जाता है। स्ट्रिंग अक्षर स्थानीय चर से अलग हैं और वे कार्यक्रम के पूरे जीवनकाल में जीवित रहते हैं। उनके पास स्थिर अवधि[रेफरी 1] जीवनकाल है।

सावधानी का एक शब्द!
हालांकि, ध्यान दें कि स्ट्रिंग अक्षर की सामग्री को संशोधित करने का कोई भी प्रयास एक अनिर्धारित व्यवहार है। उपयोगकर्ता प्रोग्रामों को एक स्ट्रिंग अक्षर की सामग्री को संशोधित करने की अनुमति नहीं है।
इसलिए, स्ट्रिंग शाब्दिक घोषित करते समय इसे const का उपयोग करने के लिए हमेशा प्रोत्साहित किया जाता है।

const char*p = "string"; 
बजाय

,

char*p = "string";  

वास्तव में, C++ यह एक स्ट्रिंग const बिना शाब्दिक हालांकि ग में नहीं घोषित करने के लिए मान्य नहीं है। हालांकि, const के साथ एक स्ट्रिंग शाब्दिक घोषित करने से आपको लाभ मिलता है कि यदि आप दूसरे मामले में स्ट्रिंग अक्षर को संशोधित करने का प्रयास करते हैं तो आमतौर पर संकलक आपको चेतावनी देंगे।

Sample program:

#include<string.h> 
int main() 
{ 
    char *str1 = "string Literal"; 
    const char *str2 = "string Literal"; 
    char source[]="Sample string"; 

    strcpy(str1,source); //No warning or error just Uundefined Behavior 
    strcpy(str2,source); //Compiler issues a warning 

    return 0; 
} 

आउटपुट:

cc1: warnings being treated as errors
prog.c: In function ‘main’:
prog.c:9: error: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type

सूचना संकलक दूसरे मामले के लिए चेतावनी दी है, लेकिन पहले के लिए नहीं।


संपादित करें:

अभिन्न शाब्दिक के साथ सौदा क्या है: क्यू उत्तर देने के लिए उपयोगकर्ताओं के एक जोड़े यहां से कहा जा रहा है?
दूसरे शब्दों में इस कोड को मान्य है:

int *foo() 
{ 
    return &(2); 
} 

जवाब है, नहीं यह कोड मान्य नहीं है, यह बीमार बनाई है है & एक संकलक त्रुटि दे देंगे।
कुछ की तरह:

prog.c:3: error: lvalue required as unary ‘&’ operand 

स्ट्रिंग शाब्दिक एल-मूल्यों, यानी हैं: आप एक स्ट्रिंग शाब्दिक का पता ले जा सकते हैं, लेकिन यह सामग्री है नहीं बदल सकते।
हालांकि, किसी भी अन्य शाब्दिक (int, float, char आदि) आर-मान (ग मानक अवधि इन के लिए एक अभिव्यक्ति का मूल्य उपयोग करता है) & उनका पता ही नहीं लिया जा सकता है।


[रेफरी 1]C99 मानक 6.4.5/5 "स्ट्रिंग literals - शब्दार्थ":

+0

क्या होगा यदि उपयोगकर्ता इस तरह की कुछ चीज़ वापस कर रहा है। char * a = &"abc"; एक वापसी; क्या यह मान्य नहीं होगा? – Ashwin

+0

@ अश्विन: स्ट्रिंग अक्षर का प्रकार 'char (*) [4]' है। ऐसा इसलिए है क्योंकि, * "abc" * का प्रकार 'char [4]' है और 4 वर्णों की सरणी में पॉइंटर को 'char (*) [4]' के रूप में घोषित किया जाता है, इसलिए यदि आपको इसका पता लेना है, तो आप इसे 'char (* a) [4] = &"abc";' और हां के रूप में करने की आवश्यकता है, यह मान्य है। –

+0

@ एएलएस "एबीसी" 'char [4]' है। (''\ 0''' के कारण) – asaelr

6

अच्छा प्रश्न है। सामान्य में, आप सही होंगे, लेकिन आपका उदाहरण अपवाद है। संकलक स्थिर रूप से एक स्ट्रिंग अक्षर के लिए वैश्विक स्मृति आवंटित करता है। इसलिए, आपके फ़ंक्शन द्वारा लौटाया गया पता मान्य है।

कि यह सी की एक सुविधाजनक सुविधा है, है ना? यह किसी फ़ंक्शन को प्रोग्रामर को उस मेमोरी के बारे में चिंता करने के लिए मजबूर किए बिना एक प्रीकंपोज्ड संदेश वापस करने की अनुमति देता है जिसमें संदेश संग्रहीत किया जाता है।

@ asaelr का सही अवलोकन पुनः const भी देखें।

+0

: यदि उपयोगकर्ता इस तरह की कुछ चीज़ वापस कर रहा है तो क्या होगा। char * a = &"abc"; एक वापसी; क्या यह मान्य नहीं होगा? – Ashwin

+0

दाएं। असल में, कोई सिर्फ 'const char * a = "abc" लिख सकता है;', '&' को छोड़कर। इसका कारण यह है कि एक डबल-उद्धृत स्ट्रिंग अपने शुरुआती चरित्र के पते पर हल हो जाती है। – thb

14

स्ट्रिंग अक्षर पूरे कार्यक्रम के लिए मान्य हैं (और स्टैक आवंटित नहीं किए जाते हैं), इसलिए यह मान्य होगा।

इसके अलावा, स्ट्रिंग शाब्दिक केवल पढ़ने के लिए कर रहे हैं, तो (अच्छा शैली के लिए) हो सकता है आप fooconst char *foo(int)

+0

क्या होगा यदि उपयोगकर्ता इस तरह की कुछ चीज़ वापस कर रहा है। char * a = &"abc"; एक वापसी; क्या यह मान्य नहीं होगा? – Ashwin

+0

'और" abc "' 'char *' नहीं है। यह सरणी का पता है, और इसका प्रकार 'char (*) [4]' है। हालांकि, या तो 'वापसी &"abc";' और 'char * a =" abc "; वापस लौटें;' मान्य हैं। – asaelr

+0

@asaelr: दरअसल, यह सिर्फ एक अच्छी शैली * के लिए * के लिए अधिक है, विवरण के लिए मेरा जवाब देखें। –

3

स्थानीय चर में बदल जानी चाहिए गुंजाइश वे घोषित कर रहे हैं के भीतर ही मान्य है, लेकिन आप किसी भी घोषित नहीं करते उस समारोह में स्थानीय चर।

यह एक फ़ंक्शन से एक स्ट्रिंग अक्षर पर एक सूचक को वापस करने के लिए पूरी तरह से मान्य है, क्योंकि प्रोग्राम के पूरे निष्पादन में एक स्ट्रिंग अक्षर मौजूद है, जैसे कि static या वैश्विक चर होगा।

यदि आप इस बारे में चिंता कर रहे हैं कि आप क्या कर रहे हैं, तो यह अमान्य हो सकता है, आपको यह देखने के लिए अपनी कंपाइलर चेतावनियां चालू करनी चाहिए कि वास्तव में कुछ भी गलत है या नहीं।

+0

क्या होगा यदि उपयोगकर्ता इस तरह की कुछ चीज़ वापस कर रहा है। char * a = &"abc"; एक वापसी; क्या यह मान्य नहीं होगा? – Ashwin

+0

@ अश्विन: 'और" एबीसी "' प्रकार 'char *' प्रकार का नहीं है, हालांकि कार्यक्रम के पूरे निष्पादन में 'abc" 'और' & "abc" 'मान्य हैं। – AusCBloke

0

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

+0

क्या होगा यदि उपयोगकर्ता इस तरह की कुछ चीज़ वापस कर रहा है। char * a = &"abc"; एक वापसी; क्या यह मान्य नहीं होगा? – Ashwin

0

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

आपको धन्यवाद,

Viharri पी एल वी

74

यह वैध है, स्ट्रिंग शाब्दिक स्थिर भंडारण अवधि है, तो सूचक झूलते नहीं है।

सी के लिए, कि, खंड 6.4.5 में अनिवार्य है पैरा 6:

In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals. The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.

और सी ++ के लिए खंड 2.14.5 में, पैराग्राफ 8-11:

8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char ”, where n is the size of the string as defined below, and has static storage duration (3.7).

9 A string literal that begins with u, such as u"asdf" , is a char16_t string literal. A char16_t string literal has type “array of n const char16_t ”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters. A single c-char may produce more than one char16_t character in the form of surrogate pairs.

10 A string literal that begins with U, such as U"asdf" , is a char32_t string literal. A char32_t string literal has type “array of n const char32_t ”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.

11 A string literal that begins with L, such as L"asdf" , is a wide string literal. A wide string literal has type “array of n const wchar_t ”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.

+0

एफवाईआई: यह उत्तर http://stackoverflow.com/questions/16470959/can-we-return-string-literal-in-c – Shog9

5

हाँ, यह वैध कोड है, नीचे केस 1। एक स्ट्रिंग शाब्दिक को

  • const char*: आप सुरक्षित रूप से कम से कम इन मायनों में एक समारोह से सी तार लौट सकते हैं। संशोधित नहीं किया जा सकता है, कॉलर द्वारा मुक्त नहीं किया जाना चाहिए। नीचे वर्णित मुक्त समस्या के कारण, डिफ़ॉल्ट मान लौटने के उद्देश्य के लिए शायद ही कभी उपयोगी। अगर आपको वास्तव में किसी फ़ंक्शन पॉइंटर को पास करने की ज़रूरत है, तो आपको समझदारी हो सकती है, इसलिए आपको स्ट्रिंग को वापस करने के लिए एक फ़ंक्शन की आवश्यकता है ..

  • char* या const char* स्थिर चार बफर में। कॉलर द्वारा मुक्त नहीं किया जाना चाहिए। संशोधित किया जा सकता है (या तो कॉलर द्वारा या तो इसे वापस करने वाले फ़ंक्शन द्वारा), लेकिन इसे वापस करने वाला फ़ंक्शन (आसानी से) एकाधिक बफर नहीं कर सकता है, इसलिए (आसानी से) थ्रेड सुरक्षित नहीं है, और कॉलर को लौटने की प्रतिलिपि बनाने की आवश्यकता हो सकती है फ़ंक्शन को दोबारा कॉल करने से पहले मूल्य।

  • char*malloc के साथ आवंटित एक बफर में। संशोधित किया जा सकता है, लेकिन आमतौर पर कॉलर द्वारा स्पष्ट रूप से मुक्त किया जाना चाहिए, और ढेर आवंटन ओवरहेड है। strdup इस प्रकार का है।

  • एक बफर है, जो समारोह (लौटे सूचक तर्क बफर के पहले तत्व को इंगित करने की जरूरत नहीं है) के लिए एक तर्क के रूप पारित किया गया था करने के लिए const char* या char*। कॉलर को बफर/मेमोरी प्रबंधन की ज़िम्मेदारी छोड़ देता है। इस मानक के कई मानक स्ट्रिंग फ़ंक्शन हैं।

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

+0

FYI से विलय कर दिया गया था: यह उत्तर http://stackoverflow.com/questions से विलय कर दिया गया था/16470 9 5 9/कैन-हम-रिटर्न-स्ट्रिंग-शाब्दिक-इन-सी – Shog9

1

str कभी पॉइंटर को लटका नहीं देगा। Because it points to static address जहां स्ट्रिंग अक्षर रहते हैं। यह लोड होने पर प्रोग्राम में readonly और global होगा। भले ही आप मुक्त या संशोधित करने का प्रयास करते हैं, फिर भी यह मेमोरी सुरक्षा के साथ प्लेटफ़ॉर्म पर segmentation faultफेंक देगा।

+0

एफवाईआई: यह उत्तर http://stackoverflow.com/questions/16470959/can-we-return-string-literal-in-c से विलय कर दिया गया था – Shog9

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

  • कोई संबंधित समस्या नहीं^_^