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




pointers hardware (10)

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

हालांकि, संकलक कुछ दिलचस्प जादू करता है, इस तथ्य के साथ आपकी मदद करने के लिए कि सामान्य स्मृति पते [कम से कम सभी आधुनिक मुख्यधारा प्रोसेसर में] बाइट-पतों हैं, और आपके पॉइंटर का ऑब्जेक्ट ऑब्जेक्ट बिल्कुल एक बाइट नहीं हो सकता है। तो अगर हमारे पास 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

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

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

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


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

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

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


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

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


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


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

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

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


सी ++ 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 तहत)।


हर्गिज नहीं।

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

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

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


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

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

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

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

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


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

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

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

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


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







hardware