बस क्या एक IntPtr वास्तव में है?


171

IntelliSense का उपयोग करने और अन्य लोगों के कोड को देखने के माध्यम से, मैं इस IntPtrप्रकार आया हूं ; हर बार इसका उपयोग करने की आवश्यकता होती है जिसे मैंने काम करने के लिए बस रखा है nullया IntPtr.Zeroपाया है। वास्तव में यह क्या है और इसका उपयोग कब / क्यों किया जाता है?

जवाबों:


158

यह एक "देशी (प्लेटफ़ॉर्म-विशिष्ट) आकार पूर्णांक है।" इसे आंतरिक रूप से दर्शाया जाता है void*लेकिन पूर्णांक के रूप में उजागर किया जाता है। जब भी आपको किसी अनवांटेड पॉइंटर को स्टोर करने की आवश्यकता हो तो आप इसका उपयोग कर सकते हैं और unsafeकोड का उपयोग नहीं करना चाहते हैं । IntPtr.Zeroप्रभावी रूप से NULL(एक अशक्त सूचक) है।


53
एक पॉइंटर एक ऐसी चीज है जो मेमोरी में एक पते की ओर इशारा करती है। प्रबंधित भाषाओं में आपके पास संदर्भ हैं (पता इधर-उधर हो सकता है) जबकि अप्रबंधित भाषाओं में आपके पास संकेत हैं (पता तय है)
कॉलिन मैके

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

5
+1 उस टिप्पणी के लिए @ 280Z28, जो मैंने अब तक देखे गए संकेत की सबसे रसीली व्याख्या है।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

9
इसे IntPtr कहा जाता है, क्योंकि इसका उपयोग अप्रबंधित मूल कोड, C / C ++ से करने के लिए, आपको एनालॉग प्रकार: intptr_t का उपयोग करना होगा। C # का IntPtr नक्शे C / C ++ के intptr_t के बिल्कुल समान है। और इसे शायद intptr_t के रूप में लागू किया गया है। C / C ++ में, intptr_t प्रकार को शून्य * प्रकार के समान आकार की गारंटी दी जाती है।
Пет15р Петров 10

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

69

यह एक ऐसा मूल्य प्रकार है जो मेमोरी एड्रेस को मूल या असुरक्षित कोड में उपयोग करने के लिए पर्याप्त है, लेकिन सुरक्षित प्रबंधित कोड में मेमोरी पते के रूप में सीधे उपयोग करने योग्य नहीं है।

आप यह IntPtr.Sizeपता लगाने के लिए उपयोग कर सकते हैं कि क्या आप 32-बिट या 64-बिट प्रक्रिया में चल रहे हैं, क्योंकि यह क्रमशः 4 या 8 बाइट्स होगा।


16
प्रक्रिया के लिए पता स्थान के आकार का पता लगाने के बारे में अच्छी बात है।
नोल्डोरिन

@ नोल्डोरिन ट्रू, लेकिन जरूरी नहीं कि विश्वसनीय हो। अतीत में, बहुत सारे आर्किटेक्चर हुए हैं जिनमें कई पॉइंटर प्रकार थे, और विंडोज पर, IntPtrउन हैंडल का प्रतिनिधित्व करने के लिए भी उपयोग किया जाता है जो आर्किटेक्चर की परवाह किए बिना 32-बिट हैं (हालांकि Sizeअभी भी उस मामले में 8 कहते हैं)। सीएलआई केवल कल्पना करता है कि यह एक पूर्णांक है जो "मूल आकार" का है, लेकिन यह वास्तव में बहुत कुछ नहीं कहता है।
लुआं

@ लुआण जो वास्तव में मेरे जवाब में कुछ भी नहीं बदलता है? IntPtr को एक मेमोरी एड्रेस होल्ड करने के लिए पर्याप्त मान के रूप में तथाकथित (और CLR स्रोत में उपयोग किया जाता है)। यह निश्चित रूप से छोटे मूल्यों को पकड़ सकता है। कुछ आर्किटेक्चर में कई पॉइंटर प्रकार होते हैं, लेकिन उनमें से एक ऐसा होना चाहिए जो सेट में सबसे बड़ा हो।
डैनियल ईयरविकर

@DanielEarwicker खैर, यह किसी भी मौजूदा .NET कार्यान्वयन के साथ कोई समस्या नहीं है, जहाँ तक मुझे पता है। हालाँकि, ऐतिहासिक (ऐतिहासिक) मुद्दा आकार के बारे में नहीं है - विभिन्न संकेत पूरी तरह से असंगत हो सकते हैं। आज के करीब एक उदाहरण में, पीएई 64-बिट पते का उपयोग करेगा भले ही "मूल सूचक आकार" अभी भी 32-बिट था। यह सभी तरह से तर्क पर वापस जाता है "क्या -32-सिस्टम सिस्टम का मतलब है, वास्तव में?" हमारे पास अब 256-बिट और 512-बिट संख्यात्मक रजिस्टर हैं, लेकिन फिर भी इसे 64-बिट कहते हैं। हालांकि आप वास्तव में अपने 64-बिट "पॉइंटर्स" के साथ 64-बिट भौतिक मेमोरी को संबोधित नहीं कर सकते हैं । यह एक गड़बड़ है।
लुआं

1
यह कुछ जटिल है, लेकिन इंटप्रा अभी भी "एक स्मृति पता संग्रहीत करने के लिए पर्याप्त बड़ा प्रकार" है। यह आपके उदाहरण में से एक लेने के लिए सबसे बड़े हार्डवेयर रजिस्टर जितना बड़ा नहीं है। यह सिर्फ इसके लिए नहीं है। यह एक स्मृति पते का प्रतिनिधित्व करने के लिए काफी बड़ा है। फिर इस तरह से सामान है: stackoverflow.com/questions/12006854/… जहाँ हमारे पास "पाइंटर" शब्द का उपयोग मेमोरी एड्रेस के अलावा किसी और चीज़ के लिए किया जा रहा है - यही कारण है कि मैंने विशेष रूप से "मेमोरी एड्रेस" कहा है।
डैनियल इयरविकर

48

यहाँ एक उदाहरण है:

मैं एक C # प्रोग्राम लिख रहा हूं जो एक हाई स्पीड कैमरा के साथ इंटरफेस करता है। कैमरा का अपना ड्राइवर है जो छवियों को प्राप्त करता है और उन्हें स्वचालित रूप से मेरे लिए कंप्यूटर की मेमोरी में लोड करता है।

इसलिए जब मैं काम करने के लिए अपने कार्यक्रम में नवीनतम छवि लाने के लिए तैयार हूं, तो कैमरा चालक मुझे एक इंट्राट्रेट के साथ प्रदान करता है जहां छवि के लिए ALREADY को भौतिक मेमोरी में संग्रहीत किया जाता है, इसलिए मुझे समय / संसाधन बनाने की ज़रूरत नहीं है एक मेमोरी को स्टोर करने के लिए मेमोरी का ब्लॉक जो पहले से मेमोरी में है। IntPtr मुझे केवल यह दिखाता है कि छवि पहले से ही कहां है।


7
तो IntPtr सरल आपको प्रबंधित कोड में एक अप्रबंधित पॉइंटर (जैसे कि आपके कैमरा ड्राइवर में उपयोग किया जाता है) का उपयोग करने की अनुमति देता है?
कॉलम रोजर्स

5
हाँ। वैसे इस मामले में, सबसे अधिक संभावना है कि कैमरा चालक हुड के तहत अप्रबंधित ड्राइवरों का उपयोग करता है, लेकिन प्रबंधित-केवल दुनिया में ठीक से संचालित करने के लिए यह मुझे डेटा के साथ सुरक्षित रूप से काम करने की अनुमति देने के लिए इंटप्रेट प्रदान करता है।
बफरज

3
तो यह सिर्फ आपको एक स्ट्रीम (बाइट सरणी) वापस क्यों नहीं देगा? मूल्य वापस करना असुरक्षित या असमर्थ क्यों है?
मफिन मैन

35

एक सीधी व्याख्या

एक IntPtr एक है पूर्णांक है जो एक के रूप में एक ही आकार है सूचक

आप नॉन-पॉइंटर टाइप में पॉइंटर वैल्यू को स्टोर करने के लिए IntPtr का उपयोग कर सकते हैं। यह सुविधा .NET में महत्वपूर्ण है क्योंकि पॉइंटर्स का उपयोग करना अत्यधिक त्रुटि वाला है और इसलिए अधिकांश संदर्भों में अवैध है। सूचक मान को "सुरक्षित" डेटा प्रकार में संग्रहीत करने की अनुमति देकर, असुरक्षित कोड सेगमेंट के बीच नलसाजी को सुरक्षित उच्च-स्तरीय कोड में लागू किया जा सकता है - या यहां तक ​​कि एक .NET भाषा में भी जो सीधे समर्थन बिंदुओं का समर्थन नहीं करता है।

IntPtr का आकार प्लेटफ़ॉर्म-विशिष्ट है, लेकिन इस विवरण पर शायद ही कभी विचार करने की आवश्यकता है, क्योंकि सिस्टम स्वचालित रूप से सही आकार का उपयोग करेगा।

"IntPtr" नाम भ्रामक है - ऐसा कुछ Handleअधिक उपयुक्त हो सकता है। मेरा प्रारंभिक अनुमान था कि "इंटप्राट" एक पूर्णांक के लिए एक संकेतक था । IntPtr का MSDN प्रलेखन नाम के अर्थ के बारे में बहुत अधिक जानकारी प्रदान किए बिना कुछ हद तक गूढ़ विस्तार में जाता है।

एक वैकल्पिक परिप्रेक्ष्य

एक IntPtrदो सीमाओं के साथ एक सूचक है:

  1. इसे सीधे तौर पर स्थगित नहीं किया जा सकता है
  2. यह उस डेटा के प्रकार को नहीं जानता है जो इसे इंगित करता है।

दूसरे शब्दों में, यह एक IntPtrतरह से है void*- लेकिन अतिरिक्त सुविधा के साथ जो इसे (लेकिन नहीं करना चाहिए) का उपयोग मूल सूचक अंकगणित के लिए किया जाना चाहिए।

किसी को अलग करने के लिए IntPtr, आप इसे एक सच्चे पॉइंटर (एक ऑपरेशन जिसे केवल "असुरक्षित" संदर्भों में प्रस्तुत किया जा सकता है) में डाल सकते हैं या आप इसे एक सहायक सहायक को पास कर सकते हैं जैसे कि InteropServices.Marshalकक्षा द्वारा प्रदान किया गया । Marshalकक्षा का उपयोग सुरक्षा का भ्रम देता है क्योंकि इसके लिए आपको स्पष्ट "असुरक्षित" संदर्भ में होने की आवश्यकता नहीं है। हालांकि, यह दुर्घटनाग्रस्त होने के जोखिम को दूर नहीं करता है जो पॉइंटर्स का उपयोग करने में निहित है।


2
"C" प्रोग्रामिंग भाषा के C99 मानक से "intptr" नाम के लिए कुछ मिसाल है। linux.die.net/man/3/intptr_t
ब्रेंट बर्नबर्न

17

एक सूचक क्या है?

सभी भाषाओं में, एक पॉइंटर एक प्रकार का वैरिएबल होता है, जो मेमोरी एड्रेस को स्टोर करता है, और आप या तो उनसे पूछ सकते हैं कि वे आपके द्वारा बताए गए पते या उनके द्वारा बताए गए पते के मूल्य को बता सकते हैं ।

एक पॉइंटर को एक तरह के बुक मार्क के रूप में माना जा सकता है। सिवाय इसके कि, किसी किताब में पेज पर जल्दी से कूदने के बजाय, एक पॉइंटर का इस्तेमाल मेमोरी के ब्लॉक या मैप ब्लॉक पर नज़र रखने के लिए किया जाता है।

अपने प्रोग्राम की मेमोरी की कल्पना करें जैसे 65535 बाइट्स के एक बड़े सरणी की तरह।

संकेत आज्ञाकारी रूप से इंगित करते हैं

पॉइंटर्स प्रत्येक मेमोरी एड्रेस को याद करते हैं, और इसलिए वे प्रत्येक मेमोरी में एक सिंगल एड्रेस को इंगित करते हैं।

एक समूह के रूप में, पॉइंटर्स मेमोरी पतों को याद करते हैं और याद करते हैं, जो आपके हर कमांड विज्ञापन को मानते हैं।

आप उनके राजा हैं।

सी # में संकेत

विशेष रूप से C # में, एक सूचक एक पूर्णांक चर है जो 0 और 65534 के बीच मेमोरी पता संग्रहीत करता है।

C # के लिए भी विशिष्ट, संकेत प्रकार int के हैं और इसलिए हस्ताक्षर किए गए हैं।

आप नकारात्मक संख्या वाले पतों का उपयोग नहीं कर सकते हैं, लेकिन न ही आप 65534 से ऊपर के पते का उपयोग कर सकते हैं। ऐसा करने का कोई भी प्रयास System.AccessViolationException को फेंक देगा।

MyPointer नामक पॉइंटर को इस तरह घोषित किया जाता है:

int * MyPointer;

C # में एक सूचक एक int है, लेकिन C # में मेमोरी पते 0 से शुरू होते हैं और 65534 तक बढ़ते हैं।

अतिरिक्त विशेष देखभाल के साथ नुकीली चीजों को संभालना चाहिए

असुरक्षित शब्द है उद्देश्य आपको डराना है, और एक बहुत अच्छे कारण के लिए: पॉइंटर्स नुकीली चीजें हैं, और नुकीली चीजें जैसे तलवार, कुल्हाड़ी, पॉइंटर्स, आदि को अतिरिक्त विशेष देखभाल के साथ संभाला जाना चाहिए।

पॉइंटर्स प्रोग्रामर को एक सिस्टम का टाइट कंट्रोल देते हैं। इसलिए की गई गलतियों के अधिक गंभीर परिणाम होने की संभावना है।

पॉइंटर्स का उपयोग करने के लिए, असुरक्षित कोड को आपके प्रोग्राम के गुणों में सक्षम करना पड़ता है, और पॉइंटर्स को विशेष रूप से असुरक्षित के रूप में चिह्नित विधियों या ब्लॉकों में उपयोग करना पड़ता है।

एक असुरक्षित ब्लॉक का उदाहरण

unsafe
{
    // Place code carefully and responsibly here.

}

पॉइंटर्स का उपयोग कैसे करें

जब चर या वस्तु घोषित या तात्कालिक होती हैं, तो उन्हें मेमोरी में संग्रहीत किया जाता है।

  • * प्रतीक उपसर्ग का उपयोग करके एक सूचक की घोषणा करें।

int *MyPointer;

  • एक चर का पता प्राप्त करने के लिए, आप उपसर्ग और प्रतीक का उपयोग करते हैं।

MyPointer = &MyVariable;

एक बार एक पता एक सूचक को सौंपा गया है, निम्नलिखित लागू होता है:

  • बिना * उपसर्ग के मेमोरी पतों को संदर्भित करने के लिए उपसर्ग के रूप में इंगित किया जा रहा है।

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • इंगित करने के लिए स्मृति पते पर संग्रहीत मान प्राप्त करने के लिए * उपसर्ग के साथ।

"MyPointer is pointing at " + *MyPointer;

चूँकि पॉइंटर एक चर है जो मेमोरी एड्रेस को धारण करता है, इस मेमोरी एड्रेस को पॉइंटर वेरिएबल में स्टोर किया जा सकता है।

बिंदुओं का उदाहरण सावधानीपूर्वक और जिम्मेदारी से उपयोग किया जा रहा है

    public unsafe void PointerTest()
    {
        int x = 100; // Create a variable named x

        int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer

        textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer

        textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.

    }

ध्यान दें कि सूचक का प्रकार एक इंट है। ऐसा इसलिए है क्योंकि C # मेमोरी पतों को पूर्णांक संख्याओं (int) के रूप में व्याख्या करता है।

यूंट के बजाय यह इंट क्यों है?

कोई अच्छा कारण नहीं है।

पॉइंटर्स का उपयोग क्यों करें?

पॉइंटर्स बहुत मज़ेदार हैं। कंप्यूटर के बहुत सारे मेमोरी द्वारा नियंत्रित होने के साथ, पॉइंटर्स एक प्रोग्रामर को अपने प्रोग्राम की मेमोरी के अधिक नियंत्रण के साथ सशक्त बनाते हैं।

मेमोरी की निगरानी।

मेमोरी के ब्लॉक को पढ़ने के लिए पॉइंटर्स का उपयोग करें और मॉनिटर करें कि समय के साथ मूल्यों को कैसे बदला जा रहा है।

इन मानों को जिम्मेदारी से बदलें और इस बात पर नज़र रखें कि आपके परिवर्तन आपके कंप्यूटर को कैसे प्रभावित करते हैं।


2
65534पॉइंटर रेंज के रूप में बहुत गलत लगता है। आपको एक संदर्भ प्रदान करना चाहिए।
ब्रेंट ब्रैडबर्न

1
मैंने इसे वोट दिया क्योंकि यह एक शानदार लेख है जो संकेत देता है। मैं आपके द्वारा बताए गए चश्मे के कुछ संदर्भ देखना चाहूंगा (जैसा कि ऊपर टिप्पणी की गई है)। तथापि; इस जवाब का सवाल से कोई लेना देना नहीं है। सवाल था System.IntPtr। मैं अंत में अपडेट किए गए उत्तर को यह बताना चाहूंगा System.IntPtrकि C # कृपया असुरक्षित पॉइंटर्स से क्या और कैसे संबंधित है।
माइकल पकेट द्वितीय

7

MSDN हमें बताता है:

IntPtr प्रकार को एक पूर्णांक के रूप में डिज़ाइन किया गया है जिसका आकार प्लेटफ़ॉर्म-विशिष्ट है। यही है, इस प्रकार का एक उदाहरण 32-बिट हार्डवेयर और ऑपरेटिंग सिस्टम पर 32-बिट और 64-बिट हार्डवेयर और ऑपरेटिंग सिस्टम पर 64-बिट होने की उम्मीद है।

IntPtr प्रकार का उपयोग उन भाषाओं द्वारा किया जा सकता है जो पॉइंटर्स का समर्थन करते हैं, और उन भाषाओं के बीच डेटा का संदर्भ देने के एक सामान्य साधन के रूप में जो पॉइंटर्स का समर्थन करते हैं और नहीं करते हैं।

इंटप्राट वस्तुओं का उपयोग हैंडल रखने के लिए भी किया जा सकता है। उदाहरण के लिए, IntPtr के उदाहरणों का बड़े पैमाने पर System.IO.FileStream वर्ग में फ़ाइल हैंडल को रखने के लिए उपयोग किया जाता है।

IntPtr प्रकार सीएलएस-अनुरूप है, जबकि UIntPtr प्रकार नहीं है। सामान्य भाषा के रनटाइम में केवल IntPtr प्रकार का उपयोग किया जाता है। UIntPtr प्रकार को ज्यादातर IntPtr प्रकार के साथ वास्तु समरूपता बनाए रखने के लिए प्रदान किया जाता है।

http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx


5

वैसे यह MSDN पेज है जो इससे संबंधित है IntPtr

पहली पंक्ति पढ़ती है:

एक प्लेटफ़ॉर्म-विशिष्ट प्रकार जो किसी सूचक या हैंडल को दर्शाने के लिए उपयोग किया जाता है।

पृष्ठ पर जाने के लिए एक सूचक या हैंडल क्या है:

IntPtr प्रकार का उपयोग उन भाषाओं द्वारा किया जा सकता है जो पॉइंटर्स का समर्थन करते हैं, और उन भाषाओं के बीच डेटा का संदर्भ देने के एक सामान्य साधन के रूप में जो पॉइंटर्स का समर्थन करते हैं और नहीं करते हैं।

इंटप्राट वस्तुओं का उपयोग हैंडल रखने के लिए भी किया जा सकता है। उदाहरण के लिए, IntPtr के उदाहरणों को फ़ाइल हैंडल को रखने के लिए System.IO.FileStream वर्ग में बड़े पैमाने पर उपयोग किया जाता है।

एक प्वाइंटर मेमोरी के एक क्षेत्र का संदर्भ होता है, जिसमें आपकी रुचि के कुछ डेटा होते हैं।

एक हैंडल एक ऑब्जेक्ट के लिए एक पहचानकर्ता हो सकता है और तरीकों / कक्षाओं के बीच पारित हो जाता है जब दोनों पक्षों को उस ऑब्जेक्ट तक पहुंचने की आवश्यकता होती है।


2

एक IntPtrएक है मान प्रकार है कि मुख्य रूप से पकड़ स्मृति पते या हैंडल करते थे। एक सूचक एक स्मृति पता है। एक सूचक टाइप किया जा सकता है (जैसे int*) या अनपेड (जैसे void*)। एक विंडोज हैंडल एक मान है जो आमतौर पर एक मेमोरी पते की तुलना में एक ही आकार (या छोटा) होता है और सिस्टम संसाधन (जैसे फ़ाइल या विंडो) का प्रतिनिधित्व करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.