Pointers in C++: Pointers के बारे में हमेंशा ये कहा जाता है कि ये समझने व उपयोग करने में काफी कठिन हैं। बात सही भी है लेकिन बात ये भी सही है कि “C” व “C++” की ताकत Pointers ही हैं। इन्हे समझे बिना “C” व “C++” को पूरी सक्षमता के साथ Use भी नहीं किया जा सकता है। जितने भी जटिल Softwares बनाए जाते हैं, सभी में Pointers की अपनी विशेष भूमिका होती है।
यदि आपने “C” Language सीखी है तो आप समझ सकते हैं कि Pointers का एक मुख्य काम Dynamic Memory Allocation भी है। “C++” में Dynamically Memory Allocation व Deletion करने के लिए दो नए Operators new व delete को समाहित किया गया है। हमने *this Pointer के बारे में समझ लिया है। ये एक ऐसा Pointer होता है जो स्वयं के Object को ही Point करता है। Pointers का प्रयोग Data को Store करने के लिए Complex Data Structures Create करने के लिए किया जाता है।
Pointers in C++ – The Addresses System
Pointers का जो Basic Idea है वह ज्यादा कठिन नहीं हैं। हमें Pointers के रूप में केवल ये समझना होता है कि Computer की हर Memory Location का एक Address होता है और इन Addresses को Variables की तरह Memory में Store किया जा सकता है। Computer की Memory के हर Byte का एक Address होता है। इन Addresses को ठीक उसी प्रकार से Number प्रदान किया गया है जिस प्रकार से किसी गली के विभिन्न मकानों को उनकी पहचान के लिए एक Number प्रदान किया जाता है। या जिस तरह से हर शहर, गांव आदि को एक Pin Code या Zip Code के रूप में एक Number प्रदान किया गया है।
यदि हम कहीं पर पत्र भेजना चाहते हैं और हमें उस गांव का नाम मालूम ना हो जहां पर पत्र को पहुंचाना है, लेकिन यदि हम उस शहर के Pin Code Number को जानते हैं, तो हमारा पत्र उस शहर तक पहुंच जाता है। ठीक यही Trick Computer की Memory के सम्बंध में भी Use की जाती है। Computer की Memory के हर Byte को 0 , 1, 2, 3, . . . , n तक क्रम से एक Number प्रदान किया गया है। यदि हमारे Computer की Memory 1 MB हो तो अन्तिम Memory Location के Byte का Number 1048575 होता है। यानी Memory के Addresses की शुरूआत हमेंशा 0 से होती है जबकि अन्त हमेंशा Memory की Size पर निर्भर करता है।
कोई भी Program जब Memory में Load होता है तो वह इन Memory Addresses की कुछ Range को Reserve कर लेता है। इसका मतलब ये हुआ कि उस Program का हर Variable व Function किसी एक निश्चित Address से Execute होना शुरू करता है। कोई Variable या Function Memory के किस Byte पर Stored है, ये जानने के लिए एक Address Operator (&) Use किया जाता है। इसे समझने के लिए निम्न Program देखिए:
#include <iostream.h> #include <conio.h> void main() { int var1 = 101; // define and initialize int var2 = 220; // three variables int var3 = 433; cout << endl << &var1 // print out the addresses << endl << &var2 // of these variables << endl << &var3; getch(); }
इस Program में तीन Integer प्रकार के Variables var1, var2 व var3 Define किए गए हैं और इन्हें क्रमश: 101, 220 व 433 मान प्रदान किए गए हैं। फिर एक cout Statement द्वारा इन तीनों Variables के Memory Cell के Address को Print किया गया है।
कोई Variable Memory में किस Actual Cell पर Store होता है, ये बात कई Factors पर निर्भर करती है। जैसे कि Program को किस Computer पर Run किया जा रहा है, Operating System कौनसा Use किया जा रहा है और कितने Program Memory में Currently Loaded हैं। इन कारणों से हम जब भी किसी Program को Run करते हैं, तो अलग-अलग समय पर हमें अलग-अलग Addresses प्राप्त हो सकते हैं। हमारे Computer के आधार पर ये मान निम्नानुसार प्राप्त हो रहे हैं-
0x0012ff88 <–address of var1
0x0012ff84 <–address of var2
0x0012ff80 <–address of var3
हमेंशा इस बात को ध्यान रखें कि Variables के Addresses कभी भी उनके मानों की तरह Constant नहीं होते हैं। यानी हमने इन तीन Variables को जो मान Initialize किए हैं, वे मान तब तक Change नहीं होंगे जब तक हम उन्हें Change ना करें। लेकिन इन Variables के मान अलग-अलग समय पर अलग-अलग स्थितियों मे अलग-अलग प्राप्त होंगे।
Insertion Operator (<<) Addresses को Hexadecimal Notation में Display करता है जिसका उपसर्ग 0x होता है। हमें केवल ये समझना है कि हर Variable एक Unique Memory Address पर Store होता है।
इस Output में हम देख सकते हैं कि तीनों Variables के Memory Location में चार-चार Bytes का अन्तर है। चूंकि हम 32-Bit Compiler Use कर रहे हैं, इसलिए इनके बीच 4 Bytes का अन्तर है। यदि हम 16-Bit Compiler Use करें, तो हमें इनके बीच का अन्तर दो-दो Bytes का दिखाई देगा। यदि हम Integer प्रकार के स्थान पर char प्रकार के तीन Variables Define करते, तो ये तीनों Variables एक Serial में Memory में Store होते। जबकि यदि हम double प्रकार के Variables Define करते तो इन Variables के बीच 8 Bytes का अन्तर होता। यानी इसी Program को यदि हम निम्नानुसार Modify करें तो इनके Output को समझा जा सकता है:
// Program #include <iostream.h> #include <conio.h> void main() { int var1, var2, var3; long double var7, var8, var9; cout << endl << &var1 // print out the addresses << endl << &var2 // of these variables << endl << &var3; cout << "\n\n"; cout << endl << &var7 // print out the addresses << endl << &var8 // of these variables << endl << &var9; getch(); } // Output 0x0012ff88 0x0012ff84 0x0012ff80 0x0012ff74 0x0012ff68 0x0012ff5c
हम देख सकते हैं कि सभी Addresses अवरोही क्रम में दिखाई दे रहे हैं। ऐसा इसलिए होता है क्योंकि सभी Automatic Variables Stack में Store होते हैं, जो कि Memory में ऊपर से नीचे की तरफ बढता (Grow होता) है। यदि हम External Variables Declare करें, तो हमें ये Address आरोही क्रम में प्राप्त होंगे, क्योंकि External Variables Heap Area में Store होते हैं और नीचे से ऊपर की तरफ बढते हैं। इसका असर देखने के लिए हमें पिछले उदाहरण के विभिन्न Variables को केवल main() Function से बाहर Declare करना होगा। वैसे हमें इन सब Technical बातों के लिए ज्यादा परेशान होने की जरूरत नहीं है। ये सब काम Compiler स्वयं करता रहता है। Variable के आगे & Operator Use करने और Reference Set करने, इन दोनों प्रकार के Statements के अन्तर को हमेंशा ध्यान में रखना चाहिए।
सारांश ये है कि हर Variable किसी ना किसी Memory Location पर Store होता है और हम & Operator से उस Variable के Addresses को देख सकते हैं। देखने के साथ ही हम उन Variables के Addresses को अन्य Variables में Store करके भी रख सकते हैं।
हमने अभी तक विभिन्न प्रकार के Variables देखे हैं, जो Characters, Integers, Float आदि प्रकार के मानों को Hold करके रखते हैं। Address भी एक प्रकार का Number ही होता है और इसे भी किसी Variable में Store किया जा सकता है।
एक ऐसा Variable जिसमें Data के रूप में किसी अन्य Variable का Address Store किया जा सकता है, Pointer Variable या Pointer कहलाता है। यदि किसी Pointer में किसी Variable का Address हो, तो हम कह सकते हैं कि वह Pointer किसी Variable को Point कर रहा है। चलिए, Pointers Variables को समझने के लिए एक Program देखते हैं:
// Program #include <iostream.h> #include <conio.h> void main() { int var1 = 101; // two integer variables int var2 = 220; cout << endl << &var1 // print addresses of variables << endl << &var2; int* ptr; // pointer to integers ptr = &var1; // pointer points to var1 cout << endl << ptr; // print pointer value ptr = &var2; // pointer points to var2 cout << endl << ptr; // print pointer value getch(); }
इस Program में हमने दो Integer Variables var1 व var2 को Define किया है और उन्हें मान 101 व 220 से Initialize किया है। फिर इनके Addresses को Print किया है। इसके बाद हमने निम्नानुसार Statement द्वारा एक Pointer Variable Define किया है:
int* ptr;
इस Statement में जो * Use किया गया है इस Statement का मतलब “Pointer to” होता है। यदि इस Statement को Right to Left पढा जाए, तो हम इसे “ptr as a Pointer to int” कह सकते हैं। इसी Statement को दूसरे शब्दों में कहें तो हम कह सकते हैं कि ये Variable Data के रूप में किसी अन्य Integer प्रकार के Variable का Address Store कर सकता है। यदि हमें किसी float प्रकार के Variable के Address को Store करना हो तो हमें निम्नानुसार Statement लिखना होगा:
float* floatVariable;
यानी
“floatVariable as a Pointer to float”
यानी हम इस floatVariable में किसी float प्रकार के Variable का Address Store कर सकते हैं।
एक बात हमेंशा ध्यान रखें कि हमें जिस प्रकार के Variable का Address Store करना होता है, उसी प्रकार का Pointer Variable भी Declare करना पडता है। यदि हम चाहें कि int प्रकार के Variable का Address float प्रकार के Variable में Store कर दें, तो Compiler हमें ऐसा नहीं करने देता है। हम Pointer Variable Declare करते समय जो * Use करते हैं, उसे चाहे int* var1 लिखें चाहे int *var1, इससे Compiler को कोई फर्क नहीं पडता है। लेकिन फिर भी इसे int* var1 ही लिखना चाहिए, क्योंकि * Data Type int का एक हिस्सा है ना कि नाम var1 का।
जब हमें एक ही Line के Syntax में एक से अधिक Pointer Variable Declare करने होते हैं, तब हमें Data Type तो एक ही बार लिखना होता है लेकिन * का प्रयोग हर Variable से पहले करना पडता है। जैसे:
double* dVar1, * dVar2, * dVar3;
हम इस Statement को निम्नानुसार भी लिख सकते हैं:
double *dVar1, *dVar2, *dVar3;
Pointer का जो Address होता है जैसे 0x12ff88 तो इसे हम Pointer Constant कह सकते हैं। एक बार जब कोई Variable किसी Memory Location को Reserve कर लेता है, तो ये Variable तब तक उस Memory Location को Reserve करके रखता है, जब तक कि Program या Variable का अन्त ना हो जाए। ये Variable उस Address से Move नहीं होता है। यानी Variables के Address का मान तब तक Constant होता है जब तक Program Run हो रहा होता है। जबकि Pointer जैसे कि dVar जिसे हम Pointer Variable कह सकते हैं, एक double Variable की तरह होता है। इसे भी हम उसी तरह से कोई मान Assign कर सकते हैं जिस प्रकार से किसी double प्रकार के Variable को कर सकते हैं।
जब हम पहली बार एक Variable Define करते हैं, तब उसमें कोई मान नहीं होता है बल्कि Garbage मान होता है, जिसका कोई मतलब नहीं होता है। जबकि जब हम Pointers की बात करते हैं तो Garbage मान Memory में किसी का Address होता है लेकिन हमें इस Address की जरूरत नहीं होती है। इसलिए इससे पहले कि किसी Pointer Variable को Use किया जाए, हमें उसे किसी ना किसी का Address प्रदान करना जरूरी होता है। इस काम को हमने हमारे Program में निम्नानुसार Statement द्वारा किया है:
ptr = &var1; <– Put Address of var1 in ptr
इसके बाद Program ptr में Stored मान को Print कर देता है जो कि वही मान होता है जो हम &var1 को Print करने पर प्राप्त करते हैं। इसी Pointer को दुबारा var2 का Address Assign किया गया है और var2 के Address को Print किया गया है। इस Program का Output कुछ निम्नानुसार प्राप्त होता है:
0x8f51fff4 <–address of var1
0x8f51fff2 <–address of var2
0x8f51fff4 <–ptr set to address of var1
0x8f51fff2 <–ptr set to address of var2
एक Pointer Variable किसी भी अन्य Variable का Address Store कर सकता है। हालांकि दोनों का Data Type समान होना चाहिए। Pointers को Use करते समय हमेंशा Pointers को Create करते ही उसे किसी ना किसी Variable के मान से Initialize करना चाहिए। क्योंकि यदि Pointer Variable को Initialize नहीं किया तो भी Pointer Variable में किसी ना किसी Memory Location का Address तो होगा ही, इसलिए Pointer Variable Program में गलत Result प्रदान करेगा और इस प्रकार के गलत परिणामों के लिए Compiler भी किसी प्रकार का कोई Error Message नहीं देता है। इसीलिए एक Pointer को यदि गलत तरीके से Use किया जाता है, तो उस Pointer से Generate होने वाले Bug को Debug करना काफी मुश्किल काम होता है। (Pointers in C++ – LinuxConfig)
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
C++ Programming Language in Hindi | Page: 666 | Format: PDF