दिलचस्प पोस्ट
एक चार सरणी में एक int स्टोर करें? एक सहयोगी वातावरण में इकाई फ़्रेमवर्क में माइग्रेशन जावास्क्रिप्ट का उपयोग कर एक पूर्ण पथ से फ़ाइल का नाम कैसे प्राप्त करें? निर्देशिका में विशिष्ट फ़ाइलों की PHP सूची मैं टीएफएस स्रोत नियंत्रण से एक विशिष्ट फाइल कैसे निकाल सकता हूं क्या मुझे सीडीएन से बूटस्ट्रैप का उपयोग करना चाहिए या अपने सर्वर पर कोई प्रतिलिपि बनाना चाहिए? मैं किसी निश्चित तिथि के सप्ताह की संख्या कैसे निर्धारित कर सकता हूं? CollapsingToolbarLayout की शुरुआत ऊंचाई सेट करें हाइबरनेट 3.5 में जेपीए 2.0 @ऑर्डर कॉलम एनोटेशन सेवा का केवल एक उदाहरण बनाएं (एंड्रॉइड) java: फ़्लोट को फ्लोट में स्ट्रिंग और स्ट्रिंग में कनवर्ट करें मैप दृश्य में एक एनोटेशन के रूप में मैं UIPopoverView कैसे प्रदर्शित करूं? (आईपैड) कक्षा के साथ चयनित फ़ील्ड के लिए रेल फॉर्म पर रूबी जावास्क्रिप्ट: क्लाइंट साइड बनाम सर्वर साइड सत्यापन उद्देश्य सी में फ्लोट करने के लिए स्ट्रिंग कन्वर्ट

पॉइंटर्स को समझने की बाधाएं क्या हैं और उनको दूर करने के लिए क्या किया जा सकता है?

सी या सी ++ में कई नये, और यहां तक ​​कि पुराने, महाविद्यालय स्तर के छात्रों के लिए भ्रम का एक प्रमुख कारक क्यों संकेतक हैं? क्या कोई उपकरण या सोचा प्रक्रियाएं हैं जो आपको समझने में मदद करती हैं कि संकेतक कैसे चर, कार्य और परे स्तर पर काम करते हैं?

क्या कुछ अच्छी अभ्यास चीजें हैं जो किसी के स्तर पर लाने के लिए किया जा सकता है, "आह-हह, मुझे मिल गया है," बिना उन्हें समग्र अवधारणा में फंस गया? असल में, परिदृश्यों की तरह ड्रिल।

Solutions Collecting From Web of "पॉइंटर्स को समझने की बाधाएं क्या हैं और उनको दूर करने के लिए क्या किया जा सकता है?"

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

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

मैंने नीचे कुछ डेल्फी कोड जोड़ दिया है, और कुछ टिप्पणियां जहां उपयुक्त हैं। मेरी दूसरी मुख्य प्रोग्रामिंग भाषा, सी # से डेल्फी को चुना है, उसी तरह मेमोरी लीक जैसी चीजों को प्रदर्शित नहीं करता है।

यदि आप पॉइंटर्स की उच्च-स्तरीय अवधारणा सीखना चाहते हैं, तो आपको नीचे दिए गए स्पष्टीकरण में "स्मृति लेआउट" लेबल वाले भागों को अनदेखा करना चाहिए। वे उदाहरण देते हैं कि परिचालन के बाद कैसी स्मृति दिखाई दे सकती है, लेकिन वे प्रकृति में अधिक निम्न-स्तर हैं। हालांकि, सही ढंग से व्याख्या करने के लिए कि बफर वास्तव में कैसे काम करता है, यह महत्वपूर्ण था कि मैंने इन आरेखों को जोड़ा।

अस्वीकरण: सभी उद्देश्यों और उद्देश्यों के लिए, यह स्पष्टीकरण और उदाहरण मेमोरी लेआउट बेहद सरल होते हैं। अगर आपको निम्न स्तर के आधार पर स्मृति से निपटने की आवश्यकता है, तो आपको अधिक जानकारी और अधिक जानकारी मिल जाएगी। हालांकि, मेमोरी और पॉइंटर्स को समझाने के इरादों के लिए, यह पर्याप्त सटीक है


मान लीजिए कि नीचे दिए गए थैज वर्ग को इस तरह दिखता है:

type THouse = class private FName : array[0..9] of Char; public constructor Create(name: PChar); end; 

जब आप घर के ऑब्जेक्ट को इनिशियलाइज़ करते हैं, तो कन्स्ट्रक्टर को दिए गए नाम निजी फ़ील्ड एफएनएम में कॉपी किया जाता है। एक निश्चित कारण के रूप में परिभाषित किया गया है एक निश्चित आकार की सरणी।

याद में, घर के आवंटन से जुड़े कुछ ऊपरी हिस्से होंगे, मैं इसे इस तरह नीचे बताएगा:

 --- [ttttNNNNNNNNNN] ---
      ^ ^
      |  |
      |  + - एफएनाम सरणी
      |
      + - ओवरहेड

"टीटीटीटी" क्षेत्र ओवरहेड है, आम तौर पर इसमें विभिन्न प्रकार के रनटाइम और भाषाओं के लिए अधिक होगा, जैसे कि 8 या 12 बाइट्स यह जरूरी है कि इस क्षेत्र में जो कुछ भी मूल्य संग्रहीत किया जाता है, वह कभी भी स्मृति आवंटक या कोर प्रणाली की पद्धति के अलावा कुछ भी नहीं बदल जाता है, या आप कार्यक्रम को क्रैश करने का जोखिम लेते हैं।


आवंटन मेमोरी

एक उद्यमी को अपने घर का निर्माण करने के लिए, और घर को पता दें। असली दुनिया के विपरीत, आवंटन को कहां से आवंटित नहीं किया जा सकता, लेकिन पर्याप्त जगह के साथ एक उपयुक्त जगह मिल जाएगी, और आवंटित स्मृति के पते को वापस रिपोर्ट कर सकते हैं।

दूसरे शब्दों में, उद्यमी मौके का चयन करेंगे।

 THouse.Create('My house'); 

मेमोरी लेआउट:

 --- [ttttNNNNNNNNNN] ---
     1234 मेरा घर

पते के साथ एक चर रखें

कागज के एक टुकड़े पर अपने नए घर को पता लिखें यह अखबार आपके घर के संदर्भ में काम करेगा। कागज के इस टुकड़े के बिना, आप खो गए हैं, और घर नहीं मिल सकता है, जब तक आप पहले से ही इसमें नहीं हैं।

 var h: THouse; begin h := THouse.Create('My house'); ... 

मेमोरी लेआउट:

     ज
     v
 --- [ttttNNNNNNNNNN] ---
     1234 मेरा घर

सूचक मूल्य कॉपी करें

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

नोट: आमतौर पर यह अवधारणा है कि मेरे पास लोगों को समझा जाने वाली सबसे समस्या है, दो बिंदुओं का अर्थ दो ऑब्जेक्ट या मेमोरी ब्लॉक नहीं है।

 var h1, h2: THouse; begin h1 := THouse.Create('My house'); h2 := h1; // copies the address, not the house ... 
     h1
     v
 --- [ttttNNNNNNNNNN] ---
     1234 मेरा घर
     ^
     h2

स्मृति को मुक्त करना

घर को ध्वस्त करें यदि आप चाहें तो आप बाद में एक नए पते के लिए कागज का पुन: उपयोग कर सकते हैं, या उस घर को पता भूलने के लिए स्पष्ट कर सकते हैं जो अब मौजूद नहीं है।

 var h: THouse; begin h := THouse.Create('My house'); ... h.Free; h := nil; 

यहां मैं पहली बार घर का निर्माण करता हूं, और इसके पते को पकड़ो। तब मैं घर के लिए कुछ करता हूँ (इसका उपयोग, कोड …, पाठक के लिए एक कवायद के रूप में छोड़ा गया), और फिर मैं इसे मुक्त करता हूं अन्त में मैं अपना वैरिएबल से पता साफ करता हूं।

मेमोरी लेआउट:

     एच <- +
     वी + - मुफ़्त से पहले
 --- [ttttNNNNNNNNNN] --- |
     1234 मेरा घर <- +

     ज (अब कहीं न कहीं अंक) <- +
                                 + - मुफ़्त के बाद
 ---------------------- |  (ध्यान दें, स्मृति अभी भी हो सकती है
     xx34 मेरा घर <- + कुछ डेटा शामिल है)

डेंगलिंग पॉइंटर

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

 var h: THouse; begin h := THouse.Create('My house'); ... h.Free; ... // forgot to clear h here h.OpenFrontDoor; // will most likely fail 

कॉल करने के बाद h का उपयोग करना .Free काम हो सकता है , लेकिन यह सिर्फ शुद्ध किस्मत है एक संभावित ऑपरेशन के बीच में, संभवतः यह किसी ग्राहक के स्थान पर विफल हो जाएगा।

     एच <- +
     वी + - मुफ़्त से पहले
 --- [ttttNNNNNNNNNN] --- |
     1234 मेरा घर <- +

     एच <- +
     वी + - मुफ्त के बाद
 ---------------------- |
     xx34 मेरा घर <- +

जैसा कि आप देख सकते हैं, अभी भी स्मृति में डेटा के अवशेषों को इंगित करता है, लेकिन क्योंकि यह पूरा नहीं हो सकता है, पहले की तरह इसका उपयोग करने में विफल हो सकता है।


स्मृति रिसाव

आप कागज के टुकड़े को खो देते हैं और घर नहीं पा सकते हैं घर अब भी कहीं और खड़ा है, और जब आप बाद में एक नया घर बनाना चाहते हैं, तो आप उस जगह का पुन: उपयोग नहीं कर सकते।

 var h: THouse; begin h := THouse.Create('My house'); h := THouse.Create('My house'); // uh-oh, what happened to our first house? ... h.Free; h := nil; 

यहाँ हम एक नए घर के पते के साथ h चर की सामग्री को ओवरराइट कर चुके हैं, लेकिन पुराना एक अभी भी खड़ा है … कहीं न कहीं। इस कोड के बाद, उस घर तक पहुंचने का कोई रास्ता नहीं है, और यह खड़ा हो जाएगा। दूसरे शब्दों में, आबंटित स्मृति को तब तक आवंटित किया जाएगा जब तक अनुप्रयोग बंद नहीं हो जाता, उस बिंदु पर ऑपरेटिंग सिस्टम इसे फाड़ देगा।

पहले आवंटन के बाद स्मृति लेआउट:

     ज
     v
 --- [ttttNNNNNNNNNN] ---
     1234 मेरा घर

दूसरे आवंटन के बाद स्मृति लेआउट:

                        ज
                        v
 --- [ttttNNNNNNNNNN] --- [ttttNNNNNNNNNN]
     1234 मेरा घर 5678 मेरा घर

इस पद्धति को प्राप्त करने का एक और अधिक आम तरीका है, इसे ऊपर से ऊपर लिखने के बजाय कुछ को मुक्त करना भूलना है। डेल्फी शब्दों में, यह निम्नलिखित विधि के साथ घटित होगा:

 procedure OpenTheFrontDoorOfANewHouse; var h: THouse; begin h := THouse.Create('My house'); h.OpenFrontDoor; // uh-oh, no .Free here, where does the address go? end; 

इस पद्धति के निष्पादन के बाद, हमारे चर में कोई जगह नहीं है कि घर का पता मौजूद है, लेकिन घर अब भी वहां है

मेमोरी लेआउट:

     एच <- +
     वी + - पॉइंटर खोने से पहले
 --- [ttttNNNNNNNNNN] --- |
     1234 मेरा घर <- +

     ज (अब कहीं न कहीं अंक) <- +
                                 + - सूचक खोने के बाद
 --- [ttttNNNNNNNNNN] --- |
     1234 मेरा घर <- +

जैसा कि आप देख सकते हैं, पुराना डेटा स्मृति में अखंड रहता है, और मेमोरी आवंटन द्वारा इसका पुन: उपयोग नहीं किया जाएगा। आबंटक उस बात का ट्रैक रखता है कि स्मृति के किस क्षेत्रों का उपयोग किया गया है, और जब तक आप इसे स्वतंत्र नहीं करेंगे तब तक उनका पुन: उपयोग नहीं किया जाएगा।


स्मृति को खाली करना लेकिन (अब अमान्य) संदर्भ रखते हुए

घर को ध्वस्त कर दें, कागज के टुकड़ों में से एक को मिटा दें, लेकिन आपके पास पुराने पते के साथ कागज का दूसरा टुकड़ा भी है, जब आप पता करने के लिए जाते हैं, तो आपको एक घर नहीं मिलेगा, लेकिन आपको खंडहर के समान कुछ मिल सकता है में से एक।

शायद आप भी एक घर मिल जाएंगे, लेकिन यह घर नहीं है जिसे आपने मूल रूप से संबोधित किया था, और इस प्रकार इसका प्रयोग करने का कोई प्रयास, जैसे कि यह आपकी है कि आप गंभीर रूप से विफल हो सकते हैं

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

 var h1, h2: THouse; begin h1 := THouse.Create('My house'); h2 := h1; // copies the address, not the house ... h1.Free; h1 := nil; h2.OpenFrontDoor; // uh-oh, what happened to our house? 

यहां घर h1 में संदर्भ के माध्यम से टूट गया था, और जब h1 को भी साफ किया गया था, h2 अभी भी पुराने, आउट-ऑफ-डेट, पता है। उस घर तक पहुंच जो अब खड़े नहीं रह सकता है या काम नहीं कर सकता है

यह ऊपर लटकती सूचक का एक भिन्नता है इसकी मेमोरी लेआउट देखें


बफर ओवररन

आप घर में ज्यादा सामान ले जा सकते हैं, आप पड़ोसियों के घर या यार्ड में आसानी से फिट कर सकते हैं। जब उस पड़ोसी घर के मालिक घर पर आते हैं, तो वह सभी प्रकार की चीजों को खोज लेगा, जिस पर वह अपना विचार करेंगे।

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

इस प्रकार, यह कोड:

 var h1, h2: THouse; begin h1 := THouse.Create('My house'); h2 := THouse.Create('My other house somewhere'); ^-----------------------^ longer than 10 characters 0123456789 <-- 10 characters 

पहले आवंटन के बाद स्मृति लेआउट:

                         h1
                         v
 ----------------------- [ttttNNNNNNNNNN]
                         5678 मेरा घर

दूसरे आवंटन के बाद स्मृति लेआउट:

     एच 2 एच 1
     vv
 --- [ttttNNNNNNNNNN] ---- [ttttNNNNNNNNNN]
     1234 मेरे दूसरे घर में कहीं भी जगह
                         ^ --- + - ^
                             |
                             + - अधिलेखित

वह हिस्सा जो अक्सर दुर्घटना का कारण होता है, जब आप उस डेटा के महत्वपूर्ण हिस्सों को अधिलेखित करते हैं जो वास्तव में यादृच्छिक रूप से नहीं बदला जाना चाहिए। उदाहरण के लिए, यह समस्या नहीं हो सकती है कि प्रोग्राम को दुर्घटनाग्रस्त होने के संदर्भ में, h1-house के कुछ हिस्सों को बदल दिया गया था, लेकिन ऑब्जेक्ट के ओवरहेड को अधिलेखित करना संभवतः दुर्घटना होगी, जब आप टूटे ऑब्जेक्ट का उपयोग करने की कोशिश करेंगे, जैसे कि अधिलेखित लिंक्स जो ऑब्जेक्ट में अन्य ऑब्जेक्ट्स में संग्रहीत होती है


लिंक्ड सूचियां

जब आप कागज के किसी टुकड़े पर एक पते का पालन करते हैं, तो आप एक घर पहुंच जाते हैं, और उस घर में एक दूसरे का पेपर होता है जिसमें उस पर एक नया पता होता है, चेन में अगले घर के लिए, और इसी तरह।

 var h1, h2: THouse; begin h1 := THouse.Create('Home'); h2 := THouse.Create('Cabin'); h1.NextHouse := h2; 

यहां हम अपने घर के घर से हमारे केबिन तक एक लिंक बनाते हैं। हम चेन का पालन कर सकते हैं जब तक कि किसी घर में कोई NextHouse संदर्भ न हो, जिसका मतलब है कि यह अंतिम एक है। हमारे सभी घरों का दौरा करने के लिए, हम निम्नलिखित कोड का इस्तेमाल कर सकते हैं:

 var h1, h2: THouse; h: THouse; begin h1 := THouse.Create('Home'); h2 := THouse.Create('Cabin'); h1.NextHouse := h2; ... h := h1; while h <> nil do begin h.LockAllDoors; h.CloseAllWindows; h := h.NextHouse; end; 

मेमोरी लेआउट (ऑब्जेक्ट में एक लिंक के रूप में अगला हाउस जोड़ा गया, चार एलएलएलएल के नीचे दिए गए आरेख में लिखा गया है):

     एच 1 एच 2
     vv
 --- [ttttNNNNNNNNNNLLLL] ---- [ttttNNNNNNNNNNLLLL]
     1234 होम + 5678 केबीन +
                    |  ^ |
                    + -------- + * (कोई लिंक नहीं)

मूल शब्दों में, मेमोरी पता क्या है?

एक मेमोरी एड्रेस मूल शब्दों में सिर्फ एक संख्या है। अगर आप स्मृति को बाइट्स की एक बड़ी श्रेणी के रूप में देखते हैं, तो पहले बाइट में पता 0 होता है, अगले एक पते 1 और ऊपर की तरफ। यह सरल है, लेकिन पर्याप्त अच्छा है

तो यह स्मृति लेआउट:

     एच 1 एच 2
     vv
 --- [ttttNNNNNNNNNN] --- [ttttNNNNNNNNNN]
     1234 मेरा घर 5678 मेरा घर

इन दो पते पर हो सकता है (बाएं सबसे – पता 0 है):

  • एच 1 = 4
  • एच 2 = 23

जिसका अर्थ है कि ऊपर सूचीबद्ध हमारी लिंक्ड सूची इस तरह दिख सकती है:

     एच 1 (= 4) एच 2 (= 28)
     vv
 --- [ttttNNNNNNNNNNLLLL] ---- [ttttNNNNNNNNNNLLLL]
     1234 घर 0028 5678 केबीन 0000
                    |  ^ |
                    + -------- + * (कोई लिंक नहीं)

यह एक पते को स्टोर करने के लिए विशिष्ट है जो "कहीं न कहीं" को शून्य पता के रूप में दर्शाता है।


बुनियादी शब्दों में, एक सूचक क्या है?

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

मेरी पहली कॉम्प साइकि क्लास में, हमने निम्नलिखित व्यायाम किया दी, यह लगभग 200 छात्रों के साथ एक व्याख्यान कक्ष था …

प्रोफेसर बोर्ड पर लिखते हैं: int john;

जॉन खड़ा है

प्रोफेसर लिखते हैं: int *sally = &john;

सैली खड़ा है, जॉन में अंक

प्रोफेसर: int *bill = sally;

विधेयक खड़ा है, जॉन पर अंक

प्रोफेसर: int sam;

सैम खड़ा है

प्रोफेसर: bill = &sam;

बिल अब सैम को इंगित करता है।

मुझे लगता है कि आपको विचार समझ आ गया है। मुझे लगता है कि हम यह करने के बारे में एक घंटे बिताए, जब तक कि हम पॉइंटेटर असाइनमेंट की बुनियादी बातों पर न जाएं।

पॉइंटर्स समझाए जाने के लिए मैंने एक समानता पाया है जो हाइपरलिंक्स है I अधिकांश लोग समझ सकते हैं कि इंटरनेट पर किसी अन्य पेज पर वेब पेज 'अंक' पर कोई लिंक होता है, और यदि आप उस हाइपरलिंक को कॉपी और पेस्ट कर सकते हैं, तो वे दोनों एक ही मूल वेब पेज पर इंगित करेंगे। यदि आप जाते हैं और उस मूल पृष्ठ को संपादित करते हैं, तो उन लिंक्स (पॉइंटर्स) में से किसी एक का पालन करें आपको उस नए अपडेटेड पेज मिलेगा।

कारण संकेत कई लोगों को भ्रमित करने लगते हैं कि वे ज्यादातर कंप्यूटर वास्तुकला में कम या कोई पृष्ठभूमि के साथ आते हैं। चूंकि बहुत से लोग यह सोचते नहीं हैं कि कंप्यूटर (मशीन) वास्तव में किस प्रकार कार्यान्वित किया जाता है – सी / सी ++ में काम करना विदेशी लगता है

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

सरल अतिरिक्त से थोड़ी अधिक आवश्यकता होती है कुछ भी संकेतक को शामिल करने जा रहा है और उन्हें यह सुनिश्चित करना है

सी / सी ++ भाषा में कई नये, और यहां तक ​​कि बूढ़े, महाविद्यालय स्तर के विद्यार्थियों के लिए भ्रम का एक प्रमुख कारक क्यों संकेत मिलता है?

एक मूल्य-चर के लिए प्लेसहोल्डर की अवधारणा – हम स्कूल में सिखाए गए कुछ चीज़ों पर मानचित्र – बीजगणित कोई वर्तमान समानांतर नहीं है, आपको यह समझने के बिना आकर्षित कर सकते हैं कि कंप्यूटर में शारीरिक रूप से स्मृति कैसे रखी जाती है, और कोई भी इस तरह की चीज़ के बारे में सोचता है जब तक कि वे निम्न स्तर की चीजों के साथ काम नहीं कर रहे हैं – सी / सी + / बाइट संचार स्तर पर ।

क्या कोई उपकरण या सोचा प्रक्रियाएं हैं जो आपको समझने में मदद करती हैं कि संकेतक कैसे चर, कार्य और परे स्तर पर काम करते हैं?

बक्से पते मुझे याद है जब मैं बेसिक को माइक्रो कंप्यूटर में सीखना सीख रहा था, इन खूबसूरत किताबें उन में गेम के साथ थीं, और कभी-कभी आपको विशेष पते पर मानों को प्रहार करना पड़ता था उनके पास बक्से के एक गुच्छा की एक तस्वीर थी, जिसे 0, 1, 2 के साथ लेबल किया गया था … और यह समझाया गया कि केवल एक छोटी सी चीज (एक बाइट) इन बक्से में फिट हो सकती है, और उनमें से बहुत कुछ – कुछ कंप्यूटर के रूप में 65535 के रूप में कई था! वे एक दूसरे के बगल में थे, और उन सभी को एक पता था।

क्या कुछ अच्छी अभ्यास चीजें हैं जो किसी के स्तर पर लाने के लिए किया जा सकता है, "आह-हह, मुझे मिल गया है," बिना उन्हें समग्र अवधारणा में फंस गया? असल में, परिदृश्यों की तरह ड्रिल।

एक ड्रिल के लिए? एक स्ट्रेट बनाएं:

 struct { char a; char b; char c; char d; } mystruct; mystruct.a = 'r'; mystruct.b = 's'; mystruct.c = 't'; mystruct.d = 'u'; char* my_pointer; my_pointer = &mystruct.b; cout << 'Start: my_pointer = ' << *my_pointer << endl; my_pointer++; cout << 'After: my_pointer = ' << *my_pointer << endl; my_pointer = &mystruct.a; cout << 'Then: my_pointer = ' << *my_pointer << endl; my_pointer = my_pointer + 3; cout << 'End: my_pointer = ' << *my_pointer << endl; 

उपरोक्त के समान उदाहरण, सी में छोड़कर:

 // Same example as above, except in C: struct { char a; char b; char c; char d; } mystruct; mystruct.a = 'r'; mystruct.b = 's'; mystruct.c = 't'; mystruct.d = 'u'; char* my_pointer; my_pointer = &mystruct.b; printf("Start: my_pointer = %c\n", *my_pointer); my_pointer++; printf("After: my_pointer = %c\n", *my_pointer); my_pointer = &mystruct.a; printf("Then: my_pointer = %c\n", *my_pointer); my_pointer = my_pointer + 3; printf("End: my_pointer = %c\n", *my_pointer); 

आउटपुट:

 Start: my_pointer = s After: my_pointer = t Then: my_pointer = r End: my_pointer = u 

शायद वह उदाहरण के आधार पर कुछ मूल बातें बताता है?

पहला कारण यह है कि मेरे पास पहले से समझने के लिए कठिन समय था, यह है कि कई स्पष्टीकरण में संदर्भ से गुजरने के बारे में कई बकवास शामिल हैं। यह सब इस मुद्दे को भ्रमित करता है। जब आप एक सूचक पैरामीटर का उपयोग करते हैं, तो आप मूल्य से गुजर रहे हैं; लेकिन मान एक पता होना चाहिए, बजाय, एक int

किसी और ने पहले से ही इस ट्यूटोरियल से लिंक किया है, लेकिन जब मैं पॉइंटर्स को समझने लगा, तब मैं उस क्षण को उजागर कर सकता हूं:

सी में पॉइंटर्स और एरे पर ट्यूटोरियल: अध्याय 3 – पॉइंटर और स्ट्रिंग्स

 int puts(const char *s); 

पल के लिए, const. अनदेखा करें पॉइटर को पॉइंटर puts() है जो एक पॉइंटर है, जो कि एक पॉइंटर का मान होता है (चूंकि सी में सभी मापदंडों को मान से पारित किया जाता है), और एक पॉइंटर का मान उस पते के लिए होता है जिसमें यह इंगित करता है, या, बस, एक पता । इस प्रकार जब हम लिखते हैं puts(strA); जैसा कि हमने देखा है, हम stras [0] का पता दे रहे हैं

जब मैं इन शब्दों को पढ़ता हूं, बादलों से अलग हो गया और सूर्य की रोशनी की बीम मुझे सूचक समझने के साथ घूम रहा था।

भले ही आप वीबी। नेट या सी # डेवलपर हैं (जैसा मैं हूं) और कभी भी असुरक्षित कोड का उपयोग नहीं करते हैं, यह अभी भी समझने योग्य है कि संकेतक कैसे काम करते हैं, या आप समझ नहीं पाएंगे कि ऑब्जेक्ट संदर्भ कैसे काम करते हैं उसके बाद आपके पास आम-लेकिन-गलत धारणा है कि एक वस्तु के संदर्भ में कोई ऑब्जेक्ट संदर्भ गुजर रहा है, ऑब्जेक्ट कॉपी करता है

पॉइंटर्स के बारे में सीखने के लिए मुझे टेड जेन्सेन के "ट्यूटोरियल ऑन पॉइंटर्स और एरेज़ इन सी" एक उत्कृष्ट संसाधन मिला। इसे 10 पाठों में विभाजित किया जाता है, जो कि संकेतक (और वे किस लिए हैं) के स्पष्टीकरण से शुरू होते हैं और फ़ंक्शन पॉइंटर्स के साथ खत्म होते हैं। http://home.netcom.com/~tjensen/ptr/cpoint.htm

वहां से आगे बढ़ते हुए, बीज गाइड टू नेटवर्क प्रोग्रामिंग यूनिक्स सॉकेट्स एपीआई को सिखाता है, जिससे आप वास्तव में मजेदार चीजें शुरू कर सकते हैं। http://beej.us/guide/bgnet/

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

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

 widget->wazzle.fizzle = fazzle.foozle->wazzle; 

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

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

मुझे लगता है कि कॉलेजों को सीखने में मदद करने के लिए कॉलेजों का सबसे अच्छा काम कर सकते हैं, अच्छे प्रदर्शन का उपयोग करने के लिए, परियोजनाओं के साथ मिलकर जो संकेतक उपयोग की आवश्यकता होती है। हजारों प्रदर्शनों की तुलना में संकेतक समझने के लिए एक कठिन परियोजना अधिक काम करेगी। प्रदर्शन आपको उथल समझ प्राप्त कर सकते हैं, लेकिन गहन शब्दों को समझने के लिए, आपको वास्तव में उनका उपयोग करना होगा।

मुझे नहीं लगता कि पॉइंटर्स एक अवधारणा के रूप में विशेष रूप से मुश्किल हैं – अधिकांश छात्रों के मानसिक मॉडल इस तरह से कुछ को मैप करते हैं और कुछ त्वरित बॉक्स स्केच मदद कर सकते हैं।

कठिनाई, जिस पर मैंने पिछले कुछ समय में अनुभव किया है और दूसरों को इसका सामना करना पड़ता है, यह है कि सी / सी ++ में पॉइंटर्स का प्रबंधन अनावश्यक रूप से जटिल हो सकता है।

मैंने सोचा था कि मैं इस सूची में एक सादृश्य जोड़ूंगा कि मुझे कम्प्यूटर साइंस ट्यूटर के रूप में पॉइंटर्स (दिन में वापस) समझाते समय बहुत मदद मिली; सबसे पहले, चलो:


चरण सेट करें :

3 रिक्त स्थान के साथ एक पार्किंग स्थल पर विचार करें, ये रिक्त स्थान गिने गए हैं:

 ------------------- | | | | | 1 | 2 | 3 | | | | | 

एक तरह से, यह मेमोरी स्थानों की तरह है, वे अनुक्रमिक और निकटवर्ती हैं … एक सरणी की तरह। अभी उनके पास कोई कार नहीं है, इसलिए यह एक खाली सरणी ( parking_lot[3] = {0} ) की तरह है।


डेटा जोड़ें

एक पार्किंग स्थल कभी भी लंबे समय तक खाली नहीं रहता … अगर ऐसा होता है तो यह व्यर्थ होगा और कोई भी कोई भी निर्माण नहीं करेगा तो हम कहते हैं कि जिस दिन दिन बढ़ता है, वह 3 कारों, एक नीली कार, एक लाल कार और एक हरे रंग की कार के साथ भर जाता है:

  1 2 3 ------------------- | o=o | o=o | o=o | | |B| | |R| | |G| | | oo | oo | oo | 

ये कारें एक समान प्रकार (कार) हैं, इसलिए यह सोचने का एक तरीका है कि हमारी कारें कुछ प्रकार के डेटा हैं (एक int कहते हैं), लेकिन उनके पास अलग-अलग मान हैं ( blue , red , green , जो कि रंग का एक रंग है)


पॉइंटर दर्ज करें

अब अगर मैं आपको इस पार्किंग स्थल में ले जाता हूं और मुझे नीली कार ढूंढने के लिए कहता हूं, तो आप एक उंगली बढ़ाते हैं और इसे नीले रंग की जगह को 1 बिंदु पर इंगित करने के लिए उपयोग करते हैं। यह एक संकेतक लेने और स्मृति पते ( int *finger = parking_lot )

आपकी उंगली (सूचक) मेरे प्रश्न का उत्तर नहीं है अपनी उंगली को देखकर मुझे कुछ नहीं कहा जाता है, लेकिन अगर मुझे लगता है कि आप उंगली कहां हैं (संकेतक को संदर्भित करना), तो मैं कार (डेटा) ढूंढ सकता हूं जो मैं ढूंढ रहा था।


पॉइन्टर को पुन: असाइन करना

अब मैं आपको एक लाल कार ढूंढने के लिए कह सकता हूं और आप अपनी उंगली को एक नई कार में रीडायरेक्ट कर सकते हैं। अब आपके पॉइंटर (पहले की तरह ही) मुझे एक ही प्रकार (कार) के नए डेटा (पार्किंग स्थल जहां लाल कार पायी जा सकती है) दिखा रहा है।

सूचक भौतिक रूप से परिवर्तित नहीं हुआ है, यह अभी भी आपकी उंगली है, बस यह डेटा दिखा रहा है जो मुझे बदल रहा था। ("पार्किंग स्थान" का पता)


डबल पॉइंटर्स (या पॉइंटर के लिए एक सूचक)

यह एक से अधिक सूचक के साथ-साथ काम करता है। मैं पूछ सकता हूं कि सूचक कहाँ है, जो लाल कार की तरफ इशारा कर रहा है और आप अपनी दूसरी अंग का उपयोग कर सकते हैं और एक उंगली से पहली उंगली तक बिंदु कर सकते हैं। (यह int **finger_two = &finger तरह है int **finger_two = &finger )

अब अगर मुझे यह जानना है कि नीली कार कहां है तो मैं दूसरी उंगली को पहली उंगली की दिशा का पालन कर सकता हूं, कार (डेटा) में।


झूलने वाला सूचक

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

  1 2 3 ------------------- | o=o | | o=o | | |B| | | |G| | | oo | | oo | 

आपका संकेतक अब भी इशारा कर रहा है कि लाल कार कहाँ थी लेकिन अब नहीं है मान लें कि एक नई कार वहां खींचती है … एक ऑरेंज कार अब अगर मैं आपको फिर से पूछता हूं, "लाल कार कहां है", आप अभी भी वहां की ओर इशारा करते हैं, लेकिन अब आप गलत हैं। यह एक लाल कार नहीं है, यह नारंगी है


पॉइंटर अंकगणित

ठीक है, तो आप अभी भी दूसरे पार्किंग स्थल पर ध्यान दे रहे हैं (अब ऑरेंज कार द्वारा कब्जा कर लिया गया है)

  1 2 3 ------------------- | o=o | o=o | o=o | | |B| | |O| | |G| | | oo | oo | oo | 

ठीक है, मेरे पास अब एक नया प्रश्न है … मैं अगले पार्किंग स्थल में कार का रंग जानना चाहता हूं। आप देख सकते हैं कि आप स्पॉट 2 पर इशारा कर रहे हैं, तो आप सिर्फ 1 जोड़ें और आप अगले स्थान पर इशारा कर रहे हैं। ( finger+1 ), चूंकि मैं जानना चाहता था कि डेटा क्या था, आपको उस स्थान की जांच करना है (न केवल उंगली) ताकि आप पॉइंटर ( *(finger+1) सम्मान कर सकें) वहां मौजूद कार (उस स्थान पर डेटा)

चित्र के एक अच्छे सेट के साथ ट्यूटोरियल का एक उदाहरण पॉइंटर्स की समझ के साथ बहुत मदद करता है ।

Joel Spolsky makes some good points about understanding pointers in his Guerrilla Guide to Interviewing article:

For some reason most people seem to be born without the part of the brain that understands pointers. This is an aptitude thing, not a skill thing – it requires a complex form of doubly-indirected thinking that some people just can't do.

I think the main barrier to understanding pointers is bad teachers.

Almost everyone are taught lies about pointers: That they are nothing more than memory addresses , or that they allow you to point to arbitrary locations .

And of course that they are difficult to understand, dangerous and semi-magical.

None of which is true. Pointers are actually fairly simple concepts, as long as you stick to what the C++ language has to say about them and don't imbue them with attributes that "usually" turn out to work in practice, but nevertheless aren't guaranteed by the language, and so aren't part of the actual concept of a pointer.

I tried to write up an explanation of this a few months ago in this blog post — hopefully it'll help someone.

(Note, before anyone gets pedantic on me, yes, the C++ standard does say that pointers represent memory addresses. But it does not say that "pointers are memory addresses, and nothing but memory addresses and may be used or thought of interchangeably with memory addresses". The distinction is important)

The problem with pointers is not the concept. It's the execution and language involved. Additional confusion results when teachers assume that it's the CONCEPT of pointers that's difficult, and not the jargon, or the convoluted mess C and C++ makes of the concept. So vast amounts of effort are poored into explaining the concept (like in the accepted answer for this question) and it's pretty much just wasted on someone like me, because I already understand all of that. It's just explaining the wrong part of the problem.

To give you an idea of where I'm coming from, I'm someone who understands pointers perfectly well, and I can use them competently in assembler language. Because in assembler language they are not referred to as pointers. They are referred to as addresses. When it comes to programming and using pointers in C, I make a lot of mistakes and get really confused. I still have not sorted this out. Let me give you an example.

When an api says:

 int doIt(char *buffer ) //*buffer is a pointer to the buffer 

what does it want?

it could want:

a number representing an address to a buffer

(To give it that, do I say doIt(mybuffer) , or doIt(*myBuffer) ?)

a number representing the address to an address to a buffer

(is that doIt(&mybuffer) or doIt(mybuffer) or doIt(*mybuffer) ?)

a number representing the address to the address to the address to the buffer

(maybe that's doIt(&mybuffer) . or is it doIt(&&mybuffer) ? or even doIt(&&&mybuffer) )

and so on, and the language involved doesn't make it as clear because it involves the words "pointer" and "reference" that don't hold as much meaning and clarity to me as "x holds the address to y" and "this function requires an address to y". The answer additionally depends on just what the heck "mybuffer" is to begin with, and what doIt intends to do with it. The language doesn't support the levels of nesting that are encountered in practice. Like when I have to hand a "pointer" in to a function that creates a new buffer, and it modifies the pointer to point at the new location of the buffer. Does it really want the pointer, or a pointer to the pointer, so it knows where to go to modify the contents of the pointer. Most of the time I just have to guess what is meant by "pointer" and most of the time I'm wrong, regardless of how much experience I get at guessing.

"Pointer" is just too overloaded. Is a pointer an address to a value? or is it a variable that holds an address to a value. When a function wants a pointer, does it want the address that the pointer variable holds, or does it want the address to the pointer variable? I'm confused.

I think that what makes pointers tricky to learn is that until pointers you're comfortable with the idea that "at this memory location is a set of bits that represent an int, a double, a character, whatever".

When you first see a pointer, you don't really get what's at that memory location. "What do you mean, it holds an address ?"

I don't agree with the notion that "you either get them or you don't".

They become easier to understand when you start finding real uses for them (like not passing large structures into functions).

The reason it's so hard to understand is not because it's a difficult concept but because the syntax is inconsistent .

  int *mypointer; 

You are first learned that the leftmost part of a variable creation defines the type of the variable. Pointer declaration does not work like this in C and C++. Instead they say that the variable is pointing on the type to the left. In this case: * mypointer is pointing on an int.

I didn't fully grasp pointers until i tried using them in C# (with unsafe), they work in exact same way but with logical and consistent syntax. The pointer is a type itself. Here mypointer is a pointer to an int.

  int* mypointer; 

Don't even get me started on function pointers…

I could work with pointers when I only knew C++. I kind of knew what to do in some cases and what not to do from trial/error. But the thing that gave me complete understanding is assembly language. If you do some serious instruction level debugging with an assembly language program you've written, you should be able to understand a lot of things.

I think that the main reason that people have trouble with it is because it's generally not taught in an interesting and engaging manner. I'd like to see a lecturer get 10 volunteers from the crowd and give them a 1 meter ruler each, get them to stand around in a certain configuration and use the rulers to point at each other. Then show pointer arithmetic by moving people around (and where they point their rulers). It'd be a simple but effective (and above all memorable) way of showing the concepts without getting too bogged down in the mechanics.

Once you get to C and C++ it seems to get harder for some people. I'm not sure if this is because they are finally putting theory that they don't properly grasp into practice or because pointer manipulation is inherently harder in those languages. I can't remember my own transition that well, but I knew pointers in Pascal and then moved to C and got totally lost.

I like the house address analogy, but I've always thought of the address being to the mailbox itself. This way you can visualize the concept of dereferencing the pointer (opening the mailbox).

For instance following a linked list: 1) start with your paper with the address 2) Go to the address on the paper 3) Open the mailbox to find a new piece of paper with the next address on it

In a linear linked list, the last mailbox has nothing in it (end of the list). In a circular linked list, the last mailbox has the address of the first mailbox in it.

Note that step 3 is where the dereference occurs and where you'll crash or go wrong when the address is invalid. Assuming you could walk up to the mailbox of an invalid address, imagine that there's a black hole or something in there that turns the world inside out 🙂

I don't think that pointers themselves are confusing. Most people can understand the concept. Now how many pointers can you think about or how many levels of indirection are you comfortable with. It doesn't take too many to put people over the edge. The fact that they can be changed accidently by bugs in your program can also make them very difficult to debug when things go wrong in your code.

I think it might actually be a syntax issue. The C/C++ syntax for pointers seems inconsistent and more complex than it needs to be.

Ironically, the thing that actually helped me to understand pointers was encountering the concept of an iterator in the c++ Standard Template Library . It's ironic because I can only assume that iterators were conceived as a generalization of the pointer.

Sometimes you just can't see the forest until you learn to ignore the trees.

The confusion comes from the multiple abstraction layers mixed together in the "pointer" concept. Programmers don't get confused by ordinary references in Java/Python, but pointers are different in that they expose characteristics of the underlying memory-architecture.

It is a good principle to cleanly separate layers of abstraction, and pointers do not do that.

The way I liked to explain it was in terms of arrays and indexes – people might not be familiar with pointers, but they generally know what an index is.

So I say imagine that the RAM is an array (and you have only 10-bytes of RAM):

 unsigned char RAM[10] = { 10, 14, 4, 3, 2, 1, 20, 19, 50, 9 }; 

Then a pointer to a variable is really just the index of (the first byte of) that variable in the RAM.

So if you have a pointer/index unsigned char index = 2 , then the value is obviously the third element, or the number 4. A pointer to a pointer is where you take that number and use it as an index itself, like RAM[RAM[index]] .

I would draw an array on a list of paper, and just use it to show things like many pointers pointing to the same memory, pointer arithmetic, pointer to pointer, and so on.

I don't see what is so confusing about pointers. They point to a location in memory, that is it stores the memory address. In C/C++ you can specify the type the pointer points to. उदाहरण के लिए:

 int* my_int_pointer; 

Says that my_int_pointer contains the address to a location that contains an int.

The problem with pointers is that they point to a location in memory, so it is easy to trail off into some location you should not be in. As proof look at the numerous security holes in C/C++ applications from buffer overflow (incrementing the pointer past the allocated boundary).

Not a bad way to grasp it, via iterators.. but keep looking you'll see Alexandrescu start complaining about them.

Many ex-C++ devs (that never understood that iterators are a modern pointer before dumping the language) jump to C# and still believe they have decent iterators.

Hmm, the problem is that all that iterators are is in complete odds at what the runtime platforms (Java/CLR) are trying to achieve: new, simple, everyone-is-a-dev usage. Which can be good, but they said it once in the purple book and they said it even before and before C:

Indirection.

A very powerful concept but never so if you do it all the way.. Iterators are useful as they help with abstraction of algorithms, another example. And compile-time is the place for an algorithm, very simple. You know code + data, or in that other language C#:

IEnumerable + LINQ + Massive Framework = 300MB runtime penalty indirection of lousy, dragging apps via heaps of instances of reference types..

"Le Pointer is cheap."

Some answers above have asserted that "pointers aren't really hard", but haven't gone on to address directly where "pointer are hard!" comes from. Some years back I tutored first year CS students (for only one year, since I clearly sucked at it) and it was clear to me that the idea of pointer is not hard. What's hard is understanding why and when you would want a pointer .

I don't think you can divorce that question – why and when to use a pointer – from explaining broader software engineering issues. Why every variable should not be a global variable, and why one should factor out similar code into functions (that, get this, use pointers to specialize their behaviour to their call site).

Just to confuse things a bit more, sometimes you have to work with handles instead of pointers. Handles are pointers to pointers, so that the back end can move things in memory to defragment the heap. If the pointer changes in mid-routine, the results are unpredictable, so you first have to lock the handle to make sure nothing goes anywhere.

http://arjay.bc.ca/Modula-2/Text/Ch15/Ch15.8.html#15.8.5 talks about it a bit more coherently than me. 🙂

Post office box number.

It's a piece of information that allows you to access something else.

(And if you do arithmetic on post office box numbers, you may have a problem, because the letter goes in the wrong box. And if somebody moves to another state — with no forwarding address — then you have a dangling pointer. On the other hand — if the post office forwards the mail, then you have a pointer to a pointer.)

Every C/C++ beginner has the same problem and that problem occurs not because "pointers are hard to learn" but "who and how it is explained". Some learners gather it verbally some visually and the best way of explaining it is to use "train" example (suits for verbal and visual example).

Where "locomotive" is a pointer which can not hold anything and "wagon" is what "locomotive" tries pull (or point to). After, you can classify the "wagon" itself, can it hold animals,plants or people (or a mix of them).