यह आलेख C++ में पॉइंटर टू पॉइंटर अवधारणा के बारे में है। पॉइंटर टू पॉइंटर किसी अन्य पॉइंटर के पते को इंगित करता है या संग्रहीत करता है और पॉइंटर्स के हेरफेर को स्वयं सक्षम बनाता है। इस अवधारणा का उपयोग करके, हम मेमोरी में किसी अन्य स्थान से पॉइंटर को आसानी से संशोधित कर सकते हैं। किसी सरणी के तत्वों में हेरफेर करने के लिए गतिशील रूप से आवंटित मेमोरी या बहु-आयामी सरणी में डबल पॉइंटर्स फायदेमंद होते हैं। हम उचित उदाहरणों के साथ C++ में इस पॉइंटर टू पॉइंटर कार्य और उपयोग पर चर्चा करेंगे।
परिदृश्य 1: पॉइंटर से पॉइंटर का स्मृति प्रतिनिधित्व
इस परिदृश्य में, डबल पॉइंटर घोषित करना पॉइंटर नाम से पहले एक अतिरिक्त तारांकन चिह्न (*) के साथ पॉइंटर घोषणा के समान है। हम C++ में डबल पॉइंटर की मेमोरी लोकेशन को आसानी से दर्शा सकते हैं। पॉइंटर से पॉइंटर का कोड स्निपेट निम्नलिखित में दिया गया है:
#शामिल करें
नेमस्पेस एसटीडी का उपयोग करना;
मुख्य प्रवेश बिंदु ( )
{
पूर्णांक अंक = पचास ;
int यहाँ * ptrr;
पीटीआर = & अंक;
int यहाँ ** ptrr1;
ptrr1 = & ptrr;
अदालत << 'सूचक स्मृति पता है: \एन ' ;
अदालत << 'ptrr (सूचक):' << ptrr << ' \एन ' ;
अदालत << '*ptrr1 (डबल पॉइंटर):' <<* ptrr1 << ' \एन ' ;
अदालत << 'पॉइंटर में मूल्य भंडार है: \एन ' ;
अदालत << '*ptrr=' <<* ptrr << एंडल;
अदालत << '**ptrr1 (सूचक से सूचक) = ' <<** ptrr1 << एंडल;
वापस करना 0 ;
}
मुख्य फ़ंक्शन में, हम एक वेरिएबल लेते हैं जिसका मेमोरी एड्रेस एक पॉइंटर में संग्रहीत करने की आवश्यकता होती है। अब, हम 'अंक' वेरिएबल प्रारंभ करते हैं। उसके बाद, हम 'ptrr' पॉइंटर घोषित करते हैं जो 'अंक' मेमोरी एड्रेस को संग्रहीत करता है। अब, हम डबल पॉइंटर घोषित करते हैं जिसका नाम '**ptrr1' है जो '*ptrr' पॉइंटर का पता संग्रहीत करता है। कोड के अंत में, हम कंसोल स्क्रीन पर पॉइंटर और डबल पॉइंटर की मेमोरी और वैल्यू प्रदर्शित करते हैं। इस कोड का आउटपुट निम्नलिखित में उल्लिखित है:
'ptrr' पॉइंटर का मेमोरी एड्रेस '0x6ffe04' है, और '*ptrr1' पॉइंटर 'ptrr' पॉइंटर का मेमोरी एड्रेस भी स्टोर करता है। पॉइंटर के अंदर संग्रहीत मान '50' है। मूलतः, डबल पॉइंटर का पता हमेशा पॉइंटर के मेमोरी एड्रेस के समान होता है।
परिदृश्य 2: फंक्शन पैरामीटर के रूप में पॉइंटर से पॉइंटर
इस परिदृश्य में, हम सीखेंगे कि किसी भी वेरिएबल में अस्थायी मेमोरी आवंटन करने के लिए पैरामीटर के रूप में किसी भी फ़ंक्शन में डबल पॉइंटर को कैसे पास किया जाए। डबल पॉइंटर वाले फ़ंक्शन पैरामीटर का कोड स्निपेट निम्नलिखित में उल्लिखित है:
#शामिल
शून्य getMemoryAddress ( int यहाँ ** डबल_पीटीआर ) {
आप मौसम = 200 ;
* डबल_पीटीआर = & अस्थायी;
}
मुख्य प्रवेश बिंदु ( ) {
int यहाँ * ptr_1;
int यहाँ ** डबल_पीटीआर;
डबल_पीटीआर = & ptr_1;
स्मृतिपता प्राप्त करें ( डबल_पीटीआर ) ;
std::cout << '**double_ptr का मान है:' << ** डबल_पीटीआर << std::endl;
वापस करना 0 ;
}
यहां, हम सीखेंगे कि C++ में पॉइंटर टू पॉइंटर अवधारणा कैसे काम करती है। याद रखें कि प्रोग्राम में एक पॉइंटर को डबल पॉइंटर के साथ काम करने के लिए घोषित किया गया है। तो, हम 'getMemoryAddress' फ़ंक्शन बनाते हैं। हम इस फ़ंक्शन को डिज़ाइन करते हैं ताकि जब हम पैरामीटर पास करें, तो यह स्वचालित रूप से डबल पॉइंटर का मेमोरी एड्रेस प्राप्त कर ले।
फ़ंक्शन में, हम 'tempp' वेरिएबल और '**double_ptr' डबल पॉइंटर लेते हैं। हम निर्दिष्ट वेरिएबल का पता जो 'टेम्पपी' है, डबल पॉइंटर और डबल पॉइंटर मानों को फ़ंक्शन के तर्क के रूप में पास करते हैं। प्रोग्राम कंसोल स्क्रीन पर मुख्य फ़ंक्शन कोड का परिणाम प्रदर्शित करता है, इसलिए मुख्य फ़ंक्शन में मौजूद सभी चीजें निष्पादन योग्य हैं। हम मुख्य फ़ंक्शन में 'ptr_1' पॉइंटर और डबल पॉइंटर को 'double_ptr' के रूप में लेते हैं। हम पॉइंटर का पता डबल पॉइंटर को पास करते हैं।
अब, हम ओवरराइड फ़ंक्शन में डबल पॉइंटर वेरिएबल को पास करते हैं और डबल पॉइंटर का परिणाम दिखाने के लिए 'काउट' आउटपुट स्ट्रीम स्टेटमेंट में पॉइंटर को पॉइंटर वेरिएबल में पास करते हैं।
जब कंपाइलर ओवरराइड फ़ंक्शन पर पहुंचता है, तो कंपाइलर चेकर जहां यह फ़ंक्शन परिभाषित होता है, फ़ंक्शन के अंदर कोड निष्पादित करता है और परिणाम को मुख्य फ़ंक्शन पर लौटाता है।
इस कोड का आउटपुट निम्नलिखित में संलग्न है:
परिणाम: डबल पॉइंटर का मान 200 है।
परिदृश्य 3: पॉइंटर से पॉइंटर के साथ 2डी ऐरे का उपयोग करना
इस उदाहरण में, हम डबल पॉइंटर वाले 2D ऐरे से निपटेंगे। हम एक ऐरे लेते हैं और पॉइंटर में ऐरे का पता पास करते हैं। इस परिदृश्य का पूरा कोड इस प्रकार दिया गया है:
मुख्य प्रवेश बिंदु ( ) {स्थिरांक पूर्णांक पंक्तियाँ = 3 ;
स्थिरांक पूर्णांक = 2 ;
int यहाँ ** मैट्रिक्स = नया इंट * [ पंक्तियों ] ;
के लिए ( पूर्णांक मैं = 0 ; मैं < पंक्तियाँ; ++मैं ) {
आव्यूह [ मैं ] = नया इंट [ कॉलम ] ;
}
के लिए ( पूर्णांक मैं = 0 ; मैं < पंक्तियाँ; ++मैं ) {
के लिए ( पूर्णत जे = 0 ; जे < कोल; ++जे ) {
आव्यूह [ मैं ] [ जे ] = मैं * कोल्स + जे;
}
}
के लिए ( पूर्णांक मैं = 0 ; मैं < पंक्तियाँ; ++मैं ) {
के लिए ( पूर्णत जे = 0 ; जे < कोल; ++जे ) {
अदालत << आव्यूह [ मैं ] [ जे ] << ' ' ;
}
अदालत << एंडल;
}
के लिए ( पूर्णांक मैं = 0 ; मैं < पंक्तियाँ; ++मैं ) {
मिटाना [ ] आव्यूह [ मैं ] ;
}
मिटाना [ ] आव्यूह;
वापस करना 0 ;
}
जैसा कि हम सभी जानते हैं, हमारे पास 2डी सरणी में कई पंक्तियाँ और कई कॉलम होते हैं। मुख्य फ़ंक्शन में, हम उन पंक्तियों और स्तंभों को आरंभ करते हैं जिनमें 'const int' होता है। उसके बाद, हम पंक्तियों के लिए मेमोरी स्पेस और प्रत्येक पंक्ति में कॉलम के लिए मेमोरी स्पेस आवंटित करते हैं। हम मैट्रिक्स डबल पॉइंटर में पॉइंटर के रूप में पंक्तियों की संख्या को '**मैट्रिक्स' के रूप में पास करते हैं। इस डबल पॉइंटर में पंक्तियों की संख्या का लूप निष्पादित या सत्य होता है। फिर, एक और आंतरिक लूप निष्पादित किया जाता है जब तक कि स्थिति झूठी न हो जाए।
मेमोरी आवंटन के बाद, हम फिर से एक सरणी में एक मान निर्दिष्ट करते हैं: पंक्तियों के लिए एक बाहरी लूप और 2डी सरणी के कॉलम के लिए एक आंतरिक लूप। आंतरिक लूप में, पंक्तियों और स्तंभों का मान डबल पॉइंटर को सौंपा जाता है और एक आवश्यक अंकगणितीय ऑपरेशन करता है। हम 2डी सरणी के मान प्रदर्शित करते हैं जैसे मेमोरी में आवंटित पंक्तियों और स्तंभों की संख्या। पंक्तियों और स्तंभों की संख्या हमेशा डबल पॉइंटर की ओर इंगित करती है जो पंक्तियों और स्तंभ मानों को संग्रहीत करता है। अंत में, हम मेमोरी को साफ़ करते हैं और इस सरणी को C++ में मेमोरी से हटा देते हैं।
डबल पॉइंटर के साथ 2D सरणी का आउटपुट निम्नलिखित में संलग्न है:
परिदृश्य 4: पॉइंटर का उपयोग करके पॉइंटर को पॉइंटर से बदलना
यहां, हम सीखेंगे कि डबल पॉइंटर घोषित करके C++ में पॉइंटर्स को कैसे स्वैप किया जाए। इस परिदृश्य का कोड स्निपेट निम्नलिखित में संलग्न है:
#शामिल करेंशून्य स्वैप ( int यहाँ ** ptrr_1, आप ** ptrr_2 ) {
int यहाँ * temp_var = * ptrr_1;
* ptrr_1 = * ptrr_2;
* ptrr_2 = temp_var;
}
मुख्य प्रवेश बिंदु ( ) {
पूर्णांक x = पंद्रह , वाई = 25 ;
int यहाँ * ptrrA = & एक्स, * पीटीआरबी = & और;
std::cout << 'स्वैप से पहले: *ptrrA है = ' << * ptrrA << ', *ptrrB है = ' << * ptrrB << std::endl;
बदलना ( & पीटीआरआरए, & ptrrB ) ;
std::cout << 'स्वैप के बाद: *ptrrA है = ' << * ptrrA << ', *ptrrB है= ' << * ptrrB << std::endl;
वापस करना 0 ;
}
सबसे पहले, हम दोनों पॉइंटर्स को फ़ंक्शन तर्क के रूप में पास करते हुए, स्वैप फ़ंक्शन बनाते हैं। स्वैप फ़ंक्शन में, हम 'temp' पॉइंटर लेते हैं और कुछ समय के लिए 'temp' में 'pointer1' का मान पास करते हैं। फिर, हम 'पॉइंटर2' का मान 'पॉइंटर1' पर पास करते हैं। अंत में, हम 'अस्थायी' सूचक का मान 'सूचक2' पर पास करते हैं।
मुख्य फ़ंक्शन में, हमें दो पॉइंटर्स की आवश्यकता होती है जिन्हें हम 'स्वैप' फ़ंक्शन में पास या ओवरराइड करते हैं। हम दिए गए पॉइंटर्स को वेरिएबल्स के पते पास करते हैं। फिर, पॉइंटर को स्वैप करने से पहले और बाद में पॉइंटर का मान प्रदर्शित होता है।
इस कोड का आउटपुट निम्नलिखित में संलग्न है:
जैसा कि हम देख सकते हैं, C++ में डबल पॉइंटर का उपयोग करके पॉइंटर के मानों को सफलतापूर्वक स्वैप किया जाता है।
निष्कर्ष
हमने निष्कर्ष निकाला कि पॉइंटर टू पॉइंटर हमेशा C++ में किसी भी पॉइंटर के मेमोरी एड्रेस को स्टोर करता है। हम किसी भी समय किसी भी पॉइंटर की मेमोरी लोकेशन का अस्थायी रूप से उपयोग करने के लिए डबल पॉइंटर का उपयोग कर सकते हैं। यह मेमोरी एड्रेस को अप्रत्यक्ष रूप से हेरफेर करने और डेटा तक पहुंचने का एक बहुत ही प्रभावी तरीका है।