संक्षिप्त सारांश
(जिसे मैं शीर्ष पर भी रखूंगा):
(0) पाइंट के बारे में सोचना पतों के रूप में अक्सर एक अच्छा शिक्षण उपकरण है, और अक्सर साधारण डेटा प्रकारों के लिए पॉइंटर्स के लिए वास्तविक कार्यान्वयन है।
(1) लेकिन कई पर, शायद सबसे अधिक, फ़ंक्शन के लिए संकलक पते पते नहीं हैं, लेकिन एक पते (आमतौर पर 2x, कभी-कभी अधिक) से बड़े हैं, या वास्तव में स्मृति में एक संरचना की ओर संकेत करते हैं, जिसमें फ़ंक्शन और सामान जैसे पते शामिल हैं एक निरंतर पूल।
(2) डेटा सदस्यों को इंगित करने और विधियों के लिए संकेत अक्सर अजनबी भी होते हैं।
(3) FAR और NEAR पॉइंटर मुद्दों के साथ लिगेसी x86 कोड
(4) कई उदाहरण, विशेष रूप से आईबीएम एएस / 400, सुरक्षित "फैट पॉइंटर्स" के साथ।
मुझे यकीन है कि आप अधिक पा सकते हैं।
विवरण:
UMMPPHHH !!!!! अब तक के कई उत्तर काफी विशिष्ट "प्रोग्रामर वेनी" उत्तर हैं - लेकिन कंपाइलर वेनी या हार्डवेयर वेनी नहीं। चूंकि मैं एक हार्डवेयर वेनी होने का दिखावा करता हूं, और अक्सर कंपाइलर वेनीज़ के साथ काम करता हूं, मुझे अपने दो सेंट में फेंक दें:
कई पर, शायद सबसे, सी कंपाइलर, प्रकार के डेटा के लिए एक सूचक T
, वास्तव में, का पता है T
।
ठीक।
लेकिन, इनमें से कई कंपाइलरों पर, कुछ पॉइंटर्स एड्रेस नहीं हैं। आप इसे देखकर बता सकते हैं sizeof(ThePointer)
।
उदाहरण के लिए, फ़ंक्शन के संकेत कभी-कभी साधारण पते की तुलना में काफी बड़े होते हैं। या, वे अप्रत्यक्ष के स्तर को शामिल कर सकते हैं। यह लेखइंटेल इटेनियम प्रोसेसर से युक्त एक विवरण प्रदान करता है, लेकिन मैंने दूसरों को देखा है। आमतौर पर, एक फ़ंक्शन को कॉल करने के लिए आपको न केवल फ़ंक्शन कोड का पता होना चाहिए, बल्कि फ़ंक्शन के स्थिर पूल का पता भी होना चाहिए - मेमोरी का एक क्षेत्र जहां से संकलक उत्पन्न होने के बजाय एक एकल लोड निर्देश के साथ लोड किए जाते हैं कई लोड तत्काल और शिफ्ट और निर्देशों के 64 बिट निरंतर। इसलिए, एक एकल 64 बिट पते के बजाय, आपको 2 64 बिट पते की आवश्यकता है। कुछ ABI (एप्लिकेशन बाइनरी इंटरफेसेस) इसे 128 बिट्स के रूप में चारों ओर ले जाते हैं, जबकि अन्य अप्रत्यक्ष स्तर का उपयोग करते हैं, फ़ंक्शन पॉइंटर के साथ वास्तव में एक फ़ंक्शन डिस्क्रिप्टर का पता होता है जिसमें 2 वास्तविक पते शामिल हैं। कौनसा अच्छा है? आपके दृष्टिकोण पर निर्भर करता है: प्रदर्शन, कोड आकार, और कुछ अनुकूलता के मुद्दे - अक्सर कोड मानता है कि एक पॉइंटर को लंबे या लंबे समय तक डाला जा सकता है, लेकिन यह भी मान सकते हैं कि लंबा लॉन्ग बिल्कुल 64 बिट्स है। ऐसा कोड मानकों के अनुरूप नहीं हो सकता है, लेकिन फिर भी ग्राहक चाहते हैं कि यह काम करे।
हममें से कई लोगों के पास पुरानी इंटेल x86 खंडित वास्तुकला की दर्दनाक यादें हैं, जिनमें NEAR POINTERs और FAR POINTERS हैं। शुक्र है कि ये अब तक लगभग विलुप्त हो चुके हैं, इसलिए केवल एक त्वरित सारांश: 16 बिट वास्तविक मोड में, वास्तविक रैखिक पता था
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
जबकि संरक्षित मोड में, यह हो सकता है
LinearAddress = SegmentRegister[SegNum].base + offset
परिणामी पते को सेगमेंट में निर्धारित सीमा के विरुद्ध जांचा जा रहा है। कुछ कार्यक्रमों में वास्तव में मानक C / C ++ FAR और NEAR पॉइंटर घोषणाओं का उपयोग नहीं किया गया था, लेकिन कई लोगों ने कहा *T
--- लेकिन कंपाइलर और लिंकर स्विच थे इसलिए, उदाहरण के लिए, कोड पॉइंटर्स पॉइंटर्स के पास हो सकते हैं, जो कुछ भी है उसके खिलाफ सिर्फ 32 बिट ऑफसेट सीएस (कोड सेगमेंट) रजिस्टर, जबकि डेटा पॉइंटर्स एफएआर पॉइंटर्स हो सकते हैं, जो कि 16 बिट खंड संख्या और 48 बिट मूल्य के लिए 32 बिट ऑफसेट निर्दिष्ट करते हैं। अब, ये दोनों मात्राएँ निश्चित रूप से पते से संबंधित हैं, लेकिन चूंकि वे समान आकार नहीं हैं, इसलिए उनमें से कौन सा पता है? इसके अलावा, सेगमेंट ने वास्तविक पते से संबंधित सामानों के अलावा केवल पठन-पाठन, पठन-पाठन, निष्पादन योग्य - की भी अनुमति दी।
एक और दिलचस्प उदाहरण, IMHO, (या, शायद, आईबीएम एएस / 400 परिवार था)। यह कंप्यूटर C ++ में OS को लागू करने वाले पहले में से एक था। इस मशीन पर पॉइंटर्स आम तौर पर वास्तविक पते के आकार के 2X थे - जैसेइस प्रस्तुति यह प्रस्तुतिकहते हैं, 128 बिट पॉइंटर्स, लेकिन वास्तविक पते 48-64 बिट्स थे, और, फिर से, कुछ अतिरिक्त जानकारी, जिसे क्षमता कहा जाता है, जिसने रीड, राइट और साथ ही बफर ओवरफ्लो को रोकने के लिए एक सीमा प्रदान की। हां: आप इसे C / C ++ के साथ कम्पेटिबल तरीके से कर सकते हैं - और अगर यह सर्वव्यापी था, तो चीनी PLA और स्लाव माफिया इतने सारे पश्चिमी कंप्यूटर सिस्टम में हैकिंग नहीं करेंगे। लेकिन ऐतिहासिक रूप से अधिकांश C / C ++ प्रोग्रामिंग ने प्रदर्शन के लिए सुरक्षा की उपेक्षा की है। सबसे दिलचस्प बात यह है कि AS400 परिवार ने ऑपरेटिंग सिस्टम को सुरक्षित पॉइंटर्स बनाने की अनुमति दी, जो कि अनवील किए गए कोड को दिया जा सकता है, लेकिन जो अनवील कोड को फोर्ज या छेड़छाड़ नहीं कर सकता है। फिर से, सुरक्षा, और मानकों का अनुपालन करते समय, बहुत ही मैला-कुचैला गैर-मानक कंप्लेंट C / C ++ कोड इतनी सुरक्षित प्रणाली में काम नहीं करेगा। फिर, आधिकारिक मानक हैं,
अब, मैं अपने सुरक्षा साबुन बॉक्स से उतरूंगा, और कुछ अन्य तरीकों का उल्लेख करूंगा जिसमें संकेत (विभिन्न प्रकार के) अक्सर पते नहीं होते हैं: डेटा सदस्यों को संकेत, सदस्य के कार्य के तरीके के संकेत, और इसके स्थैतिक संस्करण एक से बड़े हैं साधारण पता। जैसा कि यह पोस्ट कहती है:
इसे हल करने के कई तरीके हैं [एकल बनाम एकाधिक असमानता, और आभासी विरासत से संबंधित समस्याएं]। यहां बताया गया है कि विज़ुअल स्टूडियो कंपाइलर इसे कैसे हैंडल करता है: एक बहु-विरासत वाले वर्ग के सदस्य फ़ंक्शन के लिए एक सूचक वास्तव में एक संरचना है। "और वे कहते हैं" एक फ़ंक्शन पॉइंटर को कास्टिंग करने से इसका आकार बदल सकता है! "।
जैसा कि आप शायद मेरी (पर) सुरक्षा में मेरे अनंतिम से अनुमान लगा सकते हैं, मैं C / C ++ हार्डवेयर / सॉफ्टवेयर परियोजनाओं में शामिल रहा हूं जहां एक कच्चे पते की तुलना में एक पॉइंटर को क्षमता की तरह व्यवहार किया गया था।
मैं आगे बढ़ सकता था, लेकिन मुझे उम्मीद है कि आपको यह विचार मिलेगा।
संक्षिप्त सारांश
(जिसे मैं शीर्ष पर भी रखूंगा):
(0) पाइंट के रूप में पाइंटर्स के बारे में सोचना अक्सर एक अच्छा शिक्षण उपकरण होता है, और अक्सर साधारण डेटा प्रकारों के लिए पाइंटर्स के लिए वास्तविक कार्यान्वयन होता है।
(1) लेकिन कई पर, शायद सबसे अधिक, फ़ंक्शन के लिए संकलक पते पते नहीं हैं, लेकिन एक पते (आमतौर पर 2X, कभी-कभी अधिक) से बड़े होते हैं, या वास्तव में स्मृति में एक संरचना की ओर इशारा करते हैं, जिसमें फ़ंक्शन और सामान जैसे पते शामिल होते हैं एक निरंतर पूल।
(2) डेटा सदस्यों को इंगित करने और विधियों के लिए संकेत अक्सर अजनबी भी होते हैं।
(3) FAR और NEAR पॉइंटर मुद्दों के साथ लिगेसी x86 कोड
(4) कई उदाहरण, विशेष रूप से आईबीएम एएस / 400, सुरक्षित "फैट पॉइंटर्स" के साथ।
मुझे यकीन है कि आप अधिक पा सकते हैं।