मैं सी और सी ++ के लिए नया हूँ। मैं समझता हूं कि जब भी किसी फ़ंक्शन को कॉल किया जाता है, तो उसके वेरिएबल को स्टैक पर आवंटित मेमोरी मिलती है, जिसमें वह मामला शामिल होता है जहां वेरिएबल एक पॉइंटर होता है जो malloc या new के माध्यम से ढेर पर आवंटित डेटा को इंगित करता है। (लेकिन मैंने सुना है कि यह गारंटी नहीं है कि मॉलोक द्वारा आवंटित भंडारण ढेर पर 100% है, अगर मैं गलत हूं तो कृपया मुझे सही करें)। उदाहरण के लिए,

Void fn(){
    Member *p = new Member()
}
 

या

Void fn() {
        int *p = (int*) malloc( sizeof(int) * 10 );         
}

कृपया सही करें यदि मैं गलत हूं, दोनों ही मामलों में, चर p (जो ढेर पर आवंटित वस्तु का पता रखता है) स्टैक पर है, और यह ढेर पर वस्तु की ओर इशारा करता है। तो क्या यह कहना सही है कि हमारे द्वारा घोषित सभी चर स्टैक पर हैं, भले ही वे ढेर पर कुछ इंगित कर सकते हैं? मान लें कि स्थानीय चर सूचक p का पता मेमोरी एड्रेस 001 पर लोड किया गया है, इसमें हीप पर स्थित सदस्य ऑब्जेक्ट का पता है, और वह पता 002 है। हम इस तरह एक आरेख बना सकते हैं। यहां छवि विवरण दर्ज करें

यदि यह सही है, तो मेरा अगला प्रश्न यह है कि क्या हमारे पास एक पॉइंटर हो सकता है जो वास्तव में ढेर पर स्थित है, और यह स्टैक पर स्थित एक चर को इंगित करता है? यदि यह संभव नहीं है, तो क्या वह सूचक ढेर पर स्थित एक चर को इंगित कर सकता है? हो सकता है कि इस प्रश्न को वाक्यांश देने का एक और तरीका यह है: ढेर में किसी चीज़ तक पहुँचने के लिए, हम इसे केवल स्टैक पर पॉइंटर्स के माध्यम से एक्सेस कर सकते हैं ?? एक संभावित आरेख इस तरह दिख सकता है

यदि यह संभव है, तो क्या मैं यहां एक उदाहरण रख सकता हूं?

enter image description here

0
Joji 16 जिंदा 2022, 10:29
2
सी ++ को ढेर या ढेर की आवश्यकता नहीं होने के लिए निर्दिष्ट किया गया है। ढेर और ढेर का उपयोग करने वाले सिस्टम पर एक स्वचालित चर स्वचालित भंडारण में होगा और स्वचालित भंडारण एक ढेर होगा जब तक कि कार्यान्वयनकर्ता पागल न हो या एक बहुत ही रोचक समस्या हल न हो। अगर यह स्मृति में है।
 – 
user4581301
16 जिंदा 2022, 10:32
और सी के लिए भी यही सच है। (दोनों को टैग किया गया है...)
 – 
user17732522
16 जिंदा 2022, 10:33
हाय क्या मैं पूछ सकता हूं कि सी ++ द्वारा आपका क्या मतलब है ढेर या ढेर की आवश्यकता नहीं है? तो मेमोरी स्पेस को स्टैक और हीप में भी विभाजित नहीं किया गया है? @user4581301
 – 
Joji
16 जिंदा 2022, 10:33
3
- सी ++ मानक में कोई उल्लेख नहीं है कि चर कहाँ रखे गए हैं। वे रजिस्टर में हो सकते हैं।
 – 
PaulMcKenzie
16 जिंदा 2022, 10:36

4 जवाब

हां, आप अपने पॉइंटर को मुफ्त स्टोर (ढेर) पर रख सकते हैं और इसे स्टैक पर एक चर को इंगित कर सकते हैं। ट्रिक एक पॉइंटर को पॉइंटर बनाने की है (int**):

int main()
{
    int i = 0; // int on the stack

    int** ip = new int*; // create an int* (int pointer) on the free store (heap)

    // ip (the int**) is still on the stack

    *ip = &i;
    // Now your free store (heap) located pointer points
    // to your stack based variable i

    delete ip; // clean up
}

नोट: शब्द "हीप" और "स्टैक" सामान्य, अच्छी तरह से समझे जाने वाले, कंप्यूटिंग शब्द हैं। सी ++ में उन्हें मानक में "फ्री स्टोर" के रूप में संदर्भित किया जाता है और (हालांकि सीधे नाम नहीं दिया गया है) एक "स्टैक" 100% निहित है (उदाहरण के लिए "स्टैक-अनइंडिंग" के संदर्भ में) और इसलिए आवश्यक है।

3
Galik 16 जिंदा 2022, 10:48
क्या मैं पूछ सकता हूँ कि "स्थानीय चर, जिनमें पॉइंटर्स शामिल हैं, को पहले स्टैक होना चाहिए" और मेरा डायग्राम A सही है या नहीं?
 – 
Joji
16 जिंदा 2022, 10:49
आपका आरेख A आपके कोड के लिए सही है, लेकिन आपका कोड पॉइंटर्स बनाने का एकमात्र तरीका नहीं है। उनके पास स्टैक पर संबंधित चर नहीं होना चाहिए - यह ढेर पर, या स्थिर स्मृति आवंटन क्षेत्र में हो सकता है। पॉइंटर रखने वाले वेरिएबल को कहाँ स्टोर किया जाना चाहिए, इस पर कोई प्रतिबंध नहीं है।
 – 
Galik
16 जिंदा 2022, 10:52
"सी ++ में उन्हें मानक में" फ्री स्टोर "के रूप में संदर्भित किया जाता है": मानक वास्तव में उस शब्द का उपयोग नहीं करता है। ऐसा लगता है कि यह केवल एक बार सी मानक के संदर्भ में और एक बार अनुभाग शीर्षक के रूप में दिखाई देता है, जो वास्तव में लगभग operator new/operator delete है।
 – 
user17732522
16 जिंदा 2022, 10:55
क्या मैं पूछ सकता हूँ कि क्या यह कहना सही और उचित है कि ढेर में किसी चीज़ तक पहुँचने के लिए, हम इसे केवल स्टैक पर पॉइंटर्स के माध्यम से एक्सेस कर सकते हैं?
 – 
Joji
16 जिंदा 2022, 10:57
नहीं। आपको इसे एक पॉइंटर (या संभावित रूप से एक संदर्भ!) से एक्सेस करना होगा, लेकिन वह पॉइंटर कहीं भी हो सकता है।
 – 
Galik
16 जिंदा 2022, 11:00

स्टैक और ढेर मानक द्वारा विशेष रूप से परिभाषित नहीं हैं। वे कार्यान्वयन विवरण हैं।

हीप एक डेटा संरचना को संदर्भित करता है जिसका उपयोग कई ऑपरेटिंग सिस्टम एक ही समय में चल रहे विभिन्न कार्यक्रमों के लिए आवंटित स्थान को सुरक्षित रूप से प्रबंधित करने में मदद करने के लिए करते हैं। अधिक पढ़ें यहां

यहाँ एक साधारण ढेर के लिए एक आरेख है ताकि आप इसका एक मानसिक मॉडल प्राप्त कर सकें: यहां छवि विवरण दर्ज करें

ध्यान रखें कि यह ठीक वैसा नहीं है जैसा ऑपरेटिंग सिस्टम उपयोग करते हैं। वास्तव में, ऑपरेटिंग सिस्टम हीप डेटा संरचना के कहीं अधिक उन्नत रूप का उपयोग करते हैं जो उन्हें कई प्रकार के जटिल स्मृति-संबंधित कार्यों को करने की अनुमति देता है। साथ ही, प्रत्येक OS हीप डेटा संरचना का उपयोग करके मुफ़्त स्टोर लागू नहीं करता है। कुछ विभिन्न तकनीकों का उपयोग कर सकते हैं।

जबकि एक स्टैक बहुत आसान है:

enter image description here

क्या हमारे पास एक पॉइंटर हो सकता है जो वास्तव में ढेर पर स्थित है, और यह स्टैक पर स्थित एक चर को इंगित करता है?

हां, यह संभव है लेकिन शायद ही कभी इसकी आवश्यकता होती है:

#include <iostream>

int main( )
{
    int a_variable_on_stack { 5 };
    int** ptr_on_stack { new int*( &a_variable_on_stack ) };

    std::cout << "address of `a_variable_on_stack`: " << &a_variable_on_stack << '\n'
              << "address of ptr on the heap: " << ptr_on_stack << '\n'
              << "value of ptr on the heap: " << *ptr_on_stack << '\n';

    std::cin.get( );
}

संभावित आउटपुट:

address of `a_variable_on_stack`: 0x47eb5ffd2c
address of ptr on the heap: 0x1de33cc3810
value of ptr on the heap: 0x47eb5ffd2c

ध्यान दें कि a_variable_on_stack का पता और ढेर पर संग्रहीत ptr का मान दोनों 0x47eb5ffd2c कैसे हैं। दूसरे शब्दों में, ढेर पर एक सूचक ढेर पर एक चर का पता धारण कर रहा है।

2
digito_evo 16 जिंदा 2022, 11:40
क्या मैं पूछ सकता हूँ कि क्या आरेख A सही है? और क्या यह कहना सही और उचित है कि ढेर में किसी चीज़ तक पहुँचने के लिए, हम इसे केवल स्टैक पर पॉइंटर्स के माध्यम से एक्सेस कर सकते हैं?
 – 
Joji
16 जिंदा 2022, 10:58
आपका आरेख सही है। और आपका अनुमान सही है।
 – 
digito_evo
16 जिंदा 2022, 10:58
ने लिखा, "क्या यह कहना सही और उचित है कि ढेर में किसी चीज़ तक पहुँचने के लिए, हम इसे केवल स्टैक पर पॉइंटर्स के माध्यम से एक्सेस कर सकते हैं?" नहीं, यह सही नहीं है। ढेर में अक्सर हमारे पास पॉइंटर्स होते हैं जो ढेर में अन्य वस्तुओं की ओर इशारा करते हैं। कुछ उदाहरण लिंक्ड सूचियाँ और बाइनरी सर्च ट्री हैं।
 – 
user3386109
16 जिंदा 2022, 11:30
तो आप उस पहले पॉइंटर तक कैसे पहुंच सकते हैं जो ढेर पर संग्रहीत अन्य सभी पॉइंटर्स को इंगित करता है ?? यदि वह एकल सूचक खो जाता है तो आप उन तक नहीं पहुंच सकते।
 – 
digito_evo
16 जिंदा 2022, 11:32
आप "ढेर" नामक डेटा संरचना के साथ स्मृति आवंटन शब्द "ढेर" को भ्रमित कर रहे हैं। वे दो पूरी तरह से असंबंधित शब्द हैं। "ढेर" (यादृच्छिक मेमोरी स्टोर) को "ढेर" (डेटा संरचना) के रूप में लागू करने की अपेक्षा करने का कोई कारण नहीं है।
 – 
Galik
16 जिंदा 2022, 11:34

मैं सी और सी ++ के लिए नया हूँ।

आपका प्रश्न सी या सी ++ विशिष्ट नहीं है, लेकिन यह सामान्य रूप से प्रोग्रामिंग भाषाओं के बारे में है।

... जब भी किसी फ़ंक्शन को कॉल किया जाता है, तो उसके वेरिएबल को स्टैक पर आवंटित मेमोरी मिलती है ...

यह सही है: लगभग सभी कंपाइलर इसे इस तरह से करते हैं।

हालांकि, कुछ अपवाद हैं - उदाहरण के लिए SPARC या TriCore CPU पर, जिनकी एक विशेष विशेषता है...

... ढेर पर malloc या new के माध्यम से आवंटित ...

malloc और new कभी भी स्टैक पर नहीं बल्कि ढेर पर मेमोरी आवंटित नहीं करते हैं।

... गारंटी नहीं है कि मॉलोक द्वारा आवंटित भंडारण ढेर पर 100% है ...

"ढेर" शब्द के विपरीत, "ढेर" शब्द का अर्थ स्थिति से स्थिति में थोड़ा भिन्न होता है।

कुछ मामलों में, "हीप" शब्द का उपयोग एक निश्चित मेमोरी क्षेत्र को निर्दिष्ट करने के लिए किया जाता है जिसका उपयोग malloc और new द्वारा किया जाता है।

यदि उस मेमोरी क्षेत्र में पर्याप्त मेमोरी नहीं है, तो malloc (या new) ऑपरेटिंग सिस्टम से एक अलग मेमोरी क्षेत्र में मेमोरी के लिए पूछता है।

हालांकि, अन्य लोग भी उस स्मृति क्षेत्र को "ढेर" कहेंगे।

... दोनों ही मामलों में, वैरिएबल p स्टैक पर है, और यह हीप पर ऑब्जेक्ट की ओर इशारा करता है।

यह सही है।

... क्या हमारे पास एक पॉइंटर हो सकता है जो वास्तव में ढेर पर स्थित है, और यह स्टैक पर स्थित एक चर को इंगित करता है?

ज़रूर:

int ** allocatedMemory;

void myFunction()
{
    int variableOnStack;
    allocatedMemory = (int **)malloc(sizeof(int *));
    *allocatedMemory = &variableOnStack;
    ...
}

चर allocatedMemory ढेर पर कुछ डेटा को इंगित करता है और वह डेटा स्टैक पर एक चर (variableOnStack) का सूचक होता है।

हालांकि, जब फ़ंक्शन myFunction() वापस आता है, तो वेरिएबल variableOnStack अब मौजूद नहीं रहता है। मान लें कि फ़ंक्शन otherFunction() को myFunction() के बाद कहा जाता है:

void otherFunction()
{
    int a;
    int b;
    ...
}

अब हम नहीं जानते कि क्या *allocatedMemory a, b या यहां तक ​​कि "रिटर्न एड्रेस" की ओर इशारा करता है क्योंकि हम नहीं जानते कि दोनों में से कौन सा वैरिएबल एक ही एड्रेस पर स्टोर किया गया है। variableOnStack के रूप में।

अगर हम अभी **allocatedMemory को लिखते हैं तो कुछ बुरा हो सकता है...

ढेर में कुछ एक्सेस करने के लिए, हम इसे केवल स्टैक पर पॉइंटर्स के माध्यम से एक्सेस कर सकते हैं ??

... आरेख "बी" ...

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

यह सूचक हो सकता है:

  • एक वैश्विक या static चर
    ऊपर मेरे उदाहरण में, allocatedMemory एक वैश्विक चर है।
    वैश्विक और static चरों को न तो पूरी तरह से भिन्न स्मृति क्षेत्र में संग्रहीत किया जाता है (न ही ढेर और न ही ढेर)
  • स्टैक पर एक स्थानीय चर
  • सीपीयू रजिस्टर में एक स्थानीय चर
    (मैंने पहले ही लिखा है कि स्थानीय चर हमेशा स्टैक पर संग्रहीत नहीं होते हैं)

सैद्धांतिक रूप से, आरेख "बी" में स्थिति संभव है: बस चर allocatedMemory को NULL (या किसी अन्य सूचक) द्वारा अधिलेखित कर दें।

हालाँकि, एक प्रोग्राम सीधे हीप पर डेटा तक नहीं पहुँच सकता है।

इसका मतलब यह है कि p* (जो ढेर पर कुछ डेटा है) को और अधिक एक्सेस नहीं किया जा सकता है यदि ढेर के बाहर कोई और पॉइंटर नहीं है जो p* को इंगित करता है।

0
Martin Rosenau 16 जिंदा 2022, 11:57

संक्षेप में:

किसी फ़ंक्शन के भीतर घोषित चर स्टैक पर आवंटित किए जाते हैं, और जो कुछ भी आप चाहते हैं उसे इंगित कर सकते हैं (ढेर पर अन्य चर के पते और ढेर पर अन्य चर के पते के लिए)।

ढेर पर घोषित चर के लिए भी यही है। वे ढेर पर या ढेर पर चर के पते के लिए अन्य चर के पते को इंगित कर सकते हैं। यहां कोई सीमा नहीं है।

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

0
Eliyahu Machluf 16 जिंदा 2022, 12:19