c++ - स्मृति पते के रूप में सी++ पॉइंटर्स के बारे में सोचने के लिए यह कितना हद तक स्वीकार्य है?




pointers hardware (8)

जब आप सी ++ सीखते हैं, या कम से कम जब मैंने इसे सी ++ प्राइमर के माध्यम से सीखा, तो पॉइंटर्स को उन तत्वों के "स्मृति पते" कहा जाता था जिन्हें वे इंगित करते हैं। मैं सोच रहा हूं कि यह कितना हद तक सच है।

उदाहरण के लिए, दो तत्व *p1 और *p2 p2 = p1 + 1 में संपत्ति p2 = p1 + 1 या p1 = p2 + 1 p2 = p1 + 1 p1 = p2 + 1 है और केवल अगर वे भौतिक स्मृति में आसन्न हैं?


अन्य चर की तरह, सूचक एक डेटा संग्रहीत करता है जो स्मृति का पता हो सकता है जहां अन्य डेटा संग्रहीत किया जाता है।

तो, सूचक एक चर है जिसमें एक पता है और एक पता हो सकता है।

ध्यान दें, यह आवश्यक नहीं है कि एक सूचक हमेशा एक पता रखता है । इसमें एक गैर-पता आईडी / हैंडल इत्यादि हो सकती है। इसलिए, पॉइंटर को एक पते के रूप में कहना एक बुद्धिमान बात नहीं है।

आपके दूसरे प्रश्न के बारे में:

सूचक अंकगणित स्मृति के संगत खंड के लिए मान्य है। यदि p2 = p1 + 1 और दोनों पॉइंटर्स एक ही प्रकार के हैं तो p1 p2 = p1 + 1 और p1 p2 अंक स्मृति के एक संगत खंड में हैं। तो, पते p1 और p1 p2 धारण एक दूसरे के समीप हैं।


आप जो विशेष उदाहरण देते हैं:

उदाहरण के लिए, दो तत्व * पी 1 और * पी 2 में संपत्ति पी 2 = पी 1 + 1 या पी 1 = पी 2 + 1 है और केवल अगर वे भौतिक स्मृति में आसन्न हैं?

उन प्लेटफॉर्म पर असफल हो जाएंगे जिनके पास एक फ्लैट पता स्थान नहीं है, जैसे कि PIC । पीआईसी पर भौतिक स्मृति तक पहुंचने के लिए, आपको एक पता और बैंक नंबर दोनों की आवश्यकता है, लेकिन उत्तरार्द्ध बाहरी स्रोत फ़ाइल जैसे बाह्य स्रोत से लिया जा सकता है। इसलिए, अलग-अलग बैंकों के पॉइंटर्स पर अंकगणित करने से अप्रत्याशित परिणाम मिलेंगे।


ऑपरेटिंग सिस्टम आपके प्रोग्राम में भौतिक मशीन का एक अमूर्त प्रदान करता है (यानी आपका प्रोग्राम वर्चुअल मशीन में चलता है)। इस प्रकार, आपके प्रोग्राम के पास आपके कंप्यूटर के किसी भी भौतिक संसाधन तक पहुंच नहीं है, चाहे वह CPU समय, स्मृति, आदि हो; इसे केवल इन संसाधनों के लिए ओएस से पूछना है।

स्मृति के मामले में, आपका प्रोग्राम ऑपरेटिंग सिस्टम द्वारा परिभाषित वर्चुअल एड्रेस स्पेस में काम करता है। इस पता स्थान में कई क्षेत्रों जैसे स्टैक, हीप, कोड इत्यादि हैं। आपके पॉइंटर्स का मान इस आभासी पता स्थान में पते का प्रतिनिधित्व करता है। दरअसल, लगातार पते पर 2 पॉइंटर्स इस पता स्थान में लगातार स्थानों पर इंगित करेंगे।

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

निचली पंक्ति यह है कि पॉइंटर्स मेमोरी पते हैं। हालांकि, वे वर्चुअल मेमोरी स्पेस में पतों हैं और यह तय करने के लिए ऑपरेटिंग सिस्टम पर निर्भर करता है कि यह भौतिक मेमोरी स्पेस में कैसे मैप किया गया है।

जहां तक ​​आपका कार्यक्रम चिंतित है, यह कोई मुद्दा नहीं है। इस अमूर्तता का एक कारण यह है कि कार्यक्रमों का मानना ​​है कि वे मशीन के एकमात्र उपयोगकर्ता हैं। कल्पना करें कि अगर आप अपना प्रोग्राम लिखते हैं तो आपको अन्य प्रक्रियाओं द्वारा आवंटित स्मृति पर विचार करने की आवश्यकता होगी - आपको यह भी पता नहीं है कि कौन सी प्रक्रियाएं आपके साथ चल रही हैं। साथ ही, सुरक्षा को लागू करने के लिए यह एक अच्छी तकनीक है: आपकी प्रक्रिया (अलग-अलग, कम से कम सक्षम नहीं होनी चाहिए) दुर्भावनापूर्ण रूप से किसी अन्य प्रक्रिया की मेमोरी स्पेस तक पहुंच सकती है क्योंकि वे 2 अलग-अलग (वर्चुअल) मेमोरी रिक्त स्थान में चलती हैं।


किसी भी तरह का जवाब यहां पॉइंटर्स के एक विशिष्ट परिवार का उल्लेख करने में विफल रहता है - यानी पॉइंटर्स-टू-सदस्य। वे निश्चित रूप से स्मृति पते नहीं हैं।


जैसा कि कई उत्तरों पहले ही उल्लेख कर चुके हैं, उन्हें स्मृति पते के रूप में नहीं सोचा जाना चाहिए। उन उत्तरों को समझने के लिए उन उत्तरों को देखें और यहां देखें । अपने अंतिम बयान को संबोधित करते हुए

* पी 1 और * पी 2 में संपत्ति पी 2 = पी 1 + 1 या पी 1 = पी 2 + 1 है और केवल अगर वे भौतिक स्मृति में आसन्न हैं

केवल तभी सही है जब p1 और p1 p2 एक ही प्रकार के होते हैं, या एक ही आकार के प्रकार को इंगित करते हैं।


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

हालांकि, संकलक कुछ दिलचस्प जादू करता है, इस तथ्य के साथ आपकी मदद करने के लिए कि सामान्य स्मृति पते [कम से कम सभी आधुनिक मुख्यधारा प्रोसेसर में] बाइट-पतों हैं, और आपके पॉइंटर का ऑब्जेक्ट ऑब्जेक्ट बिल्कुल एक बाइट नहीं हो सकता है। तो अगर हमारे पास T* ptr; , ptr++ करेगा ((char*)ptr) + sizeof(T); या ptr + n है ((char*)ptr) + n*sizeof(T) । इसका यह भी अर्थ है कि आपके p1 == p2 + 1 लिए p1 p1 == p2 + 1 और p1 p2 एक ही प्रकार के T , क्योंकि +1 वास्तव में +sizeof(T)*1

उपर्युक्त "पॉइंटर्स मेमोरी एड्रेस" के लिए एक अपवाद है, और यह सदस्य फ़ंक्शन पॉइंटर्स है। वे "विशेष" हैं, और अभी के लिए, कृपया केवल अनदेखा करें कि वे वास्तव में कैसे कार्यान्वित किए जाते हैं, यह कहने के लिए पर्याप्त है कि वे "केवल स्मृति पते" नहीं हैं।


मुझे लगता है कि share का सही विचार है लेकिन खराब शब्दावली है। क्या सी पॉइंटर्स प्रदान करते हैं अबास्ट्रक्शन के बिल्कुल विपरीत हैं।

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

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

सी ++ पॉइंटर्स एक चीज जोड़ते हैं जिसमें सी शामिल नहीं है। यह ऑर्डर के लिए उसी प्रकार के सभी पॉइंटर्स की तुलना करने की अनुमति देता है, भले ही वे एक ही सरणी में न हों। इससे थोड़ा अधिक मानसिक मॉडल की अनुमति मिलती है, भले ही यह हार्डवेयर को पूरी तरह मेल नहीं खाती है।


सी ++ 14 मानक के अनुसार, [expr.unary.op] / 3:

यूनरी & ऑपरेटर का परिणाम अपने ऑपरेंड के लिए एक सूचक है। ऑपरेंड एक लेल्यू या योग्य-आईडी होगा। यदि ऑपरेंड टाइप क्लास के C कुछ कक्षा C गैर-स्थैतिक सदस्य m नामक एक योग्य-आईडी नामकरण है, तो परिणाम "टाइप T के वर्ग C के सदस्य के लिए सूचक" टाइप करता है और यह C::m नामक एक प्रक्षेपण C::m । अन्यथा, यदि अभिव्यक्ति का प्रकार T , तो परिणाम "टी से पॉइंटर" टाइप करता है और यह एक प्रबुद्ध है जो निर्दिष्ट ऑब्जेक्ट का पता है या नामित फ़ंक्शन पर पॉइंटर है। [नोट: विशेष रूप से, एक सीवी-योग्यता के साथ "सीवी T " प्रकार की वस्तु का पता "सीवी T सूचक" है । नोट नोट]

तो यह स्पष्ट रूप से और स्पष्ट रूप से कहता है कि पॉइंटर्स ऑब्जेक्ट प्रकार (यानी एक T * , जहां T फ़ंक्शन प्रकार नहीं है) पते रखें।

"पता" [intro.memory] / 1 द्वारा परिभाषित किया गया है:

सी ++ प्रोग्राम में उपलब्ध स्मृति में संगत बाइट्स के एक या अधिक अनुक्रम होते हैं। प्रत्येक बाइट का एक अनूठा पता होता है।

तो एक पता कुछ भी हो सकता है जो विशिष्ट रूप से स्मृति के एक विशेष बाइट की पहचान करता है।

नोट: सी ++ मानक शब्दावली में, स्मृति केवल उस स्थान को संदर्भित करती है जो उपयोग में है। इसका मतलब भौतिक स्मृति, या आभासी स्मृति, या ऐसा कुछ भी नहीं है। स्मृति आवंटन का एक पृथक सेट है।

यह ध्यान में रखना महत्वपूर्ण है कि, हालांकि स्मृति में प्रत्येक बाइट को विशिष्ट रूप से पहचानने का एक संभावित तरीका भौतिक या आभासी स्मृति के प्रत्येक बाइट को एक अद्वितीय पूर्णांक असाइन करना है, यह एकमात्र संभव तरीका नहीं है।

गैर-पोर्टेबल कोड लिखने से बचने के लिए यह मानना ​​अच्छा होता है कि पता एक पूर्णांक के समान है। पॉइंटर्स के लिए अंकगणितीय के नियम वैसे भी पूर्णांक के लिए अंकगणितीय के नियमों के लिए अलग हैं। इसी तरह, हम यह नहीं कहेंगे कि 5.0f जैसा ही है, भले ही उनके पास स्मृति में समान प्रतिनिधित्व है ( 1084227584 तहत)।





hardware