c++ - पॉइंटर्स का उपयोग कर एक अलग फ़ंक्शन से स्थानीय चर का उपयोग कैसे करें?




pointers local-variables (6)

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

क्या मेरे पास एक अलग चर में स्थानीय चर के लिए कोई पहुंच हो सकती है? यदि हां, तो कैसे?

void replaceNumberAndPrint(int array[3]) {
    printf("%i\n", array[1]);
    printf("%i\n", array[1]);
}

int * getArray() {
    int myArray[3] = {4, 65, 23};
    return myArray;
}

int main() {
    replaceNumberAndPrint(getArray());
}

उपरोक्त कोड के टुकड़े का उत्पादन:

65
4202656

मैं क्या गलत कर रहा हूं? "4202656" का क्या अर्थ है?

क्या मुझे replaceNumberAndPrint() फ़ंक्शन में पहली सरणी को पहली बार एक्सेस करने में सक्षम होने के लिए प्रतिलिपि बनाना है?


इस कोड में आपने स्थानीय ऑब्जेक्ट्स के लिए पॉइंटर का उपयोग किया है, लेकिन जब कोई फंक्शन लौटाता है तो सभी स्थानीय चर गुंजाइश से बाहर हो जाते हैं। यदि आप स्मृति आवंटित करेंगे (आवंटन के लिए malloc() फ़ंक्शन का उपयोग करके) तो कोई डेटा खो जाएगा या ओवरराइट नहीं होगा।

int* getArray(int size) {
    int *myArray = (int*)malloc(size*sizeof(int));
    myArray[0] = 4;
    myArray[1] = 65;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int i;
    int *vector = getArray(3);
    for(i=0;i<3;i++)
    {
        printf("%i\n",vector[i]);
    }
    getch();
    return 0;
}

यह कोड सभी सरणी तत्वों को मुद्रित करेगा और कोई ओवरराइट नहीं किया जाएगा।


ऐसा करने का सही तरीका निम्नानुसार है:

struct Arr {
   int array[3];
};
Arr get_array() {
   Arr a;
   a.array[0] = 4;
   a.array[1] = 65;
   a.array[2] = 23;
   return a;
}
int main(int argc, char **argv) {
   Arr a = get_array();
   for(size_t i=0; i<3; i++)
       printf("%d\n", a.array[i]);
   return 0;
}

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


ऐसा कुछ कोशिश करो। जिस तरह से आप इसे स्थानीय रूप से परिभाषित करते हैं, तो मेरा myArray कारण "मारता है"।

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
 printf("%i\n", array[0]);
 printf("%i\n", array[1]);
 printf("%i\n" , array[2]);
 free(array);
}

int * getArray() {
 int * myArray = malloc(sizeof(int) * 3);
 myArray[0] = 4;
 myArray[1] = 64;
 myArray[2] = 23;
 //{4, 65, 23};
 return myArray;
}

int main() {
 replaceNumberAndPrint(getArray());
}

अधिक: http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/

संपादित करें: टिप्पणियों के रूप में सही ढंग से इंगित किया गया: ऐसा करने का एक बेहतर तरीका यह होगा कि:

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
    if(!array)
        return;

    printf("%i\n", array[0]);
    printf("%i\n", array[1]);
    printf("%i\n" , array[2]);
}

int * createArray() {
    int * myArray = malloc(sizeof(int) * 3);

    if(!myArray)
        return 0;

    myArray[0] = 4;
    myArray[1] = 64;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int * array = createArray();
    if(array)
    {
        replaceNumberAndPrint(array);
        free(array);
    }
    return 0;
}

स्थानीय चर वापस लौटने से गुंजाइश से बाहर जाते हैं, इसलिए आप एक स्थानीय चर के लिए एक सूचक वापस नहीं कर सकते हैं।

आपको malloc या new का उपयोग करके इसे गतिशील रूप से (ढेर पर) आवंटित करने की आवश्यकता है। उदाहरण:

int *create_array(void) {
    int *array = malloc(3 * sizeof(int));
    assert(array != NULL);
    array[0] = 4;
    array[1] = 65;
    array[2] = 23;
    return array;
 }
 void destroy_array(int *array) {
     free(array);
 }
 int main(int argc, char **argv) {
     int *array = create_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     destroy_array(array);
     return 0;
 }

वैकल्पिक रूप से, आप सरणी को अलग मानते हुए, सरणी को स्थिर मान सकते हैं। उदाहरण:

int *get_array(void) {
    static int array[] = { 4, 65, 23 };
    return array;
 }
 int main(int argc, char **argv) {
     int *array = get_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     return 0;
 }

यदि आपको नहीं पता कि static अर्थ क्या हैं, तो इस प्रश्न और उत्तर को पढ़ें।


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

अभ्यास में क्या होता है कि printf को कॉल myArray द्वारा उपयोग किए गए स्टैक के हिस्से को ओवरराइट करता है और उसके बाद इसमें कुछ अन्य डेटा होता है।

अपने कोड को ठीक करने के लिए आपको सरणी को उस दायरे में घोषित करने की आवश्यकता है जो लंबे समय तक रहता है (आपके उदाहरण में main कार्य) या इसे ढेर पर आवंटित करें। यदि आप इसे ढेर पर आवंटित करते हैं तो आपको इसे मैन्युअल रूप से या RAII का उपयोग करके C ++ में मुक्त करने की आवश्यकता है।

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





local-variables