2012-11-01 27 views
11

आई/पी देख रहा था RegOpenKeyEx की घोषणा आह्वान जब मैं पृष्ठ पर इस टिप्पणी पर ध्यान:अंतर

IntPtrUIntPtr को परिवर्तित: जब हैंडल के लिए IntPtr साथ लागू, आप चलेंगे एक ओवरफ्लो में UIntPtr सही विकल्प है यदि आप इसे 32 और 64 बिट प्लेटफ़ॉर्म पर सही तरीके से काम करना चाहते हैं।

यह मेरे लिए बहुत मतलब नहीं है: IntPtr और UIntPtr दोनों संकेत प्रतिनिधित्व करने के लिए तो उनके आकार ओएस की bitness से मेल खाना चाहिए अपेक्षा की जाती है - या तो 32 बिट या 64 बिट्स। चूंकि ये संख्याएं नहीं हैं लेकिन पॉइंटर्स हैं, उनके हस्ताक्षरित संख्यात्मक मूल्यों से कोई फर्क नहीं पड़ता, केवल उन बिट्स जो पते का प्रतिनिधित्व करते हैं। मैं किसी भी कारण से नहीं सोच सकता कि इन दोनों के बीच अंतर क्यों होगा लेकिन इस टिप्पणी ने मुझे अनिश्चित बना दिया।

IntPtr के बजाय UIntPtr का उपयोग करने का कोई विशिष्ट कारण है? documentation के अनुसार:

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

यह, वास्तव में, इसका तात्पर्य है कि इसमें कोई अंतर नहीं है (जब तक कोई मान को पूर्णांक में परिवर्तित करने की कोशिश नहीं करता)। तो pinvoke.net से उपर्युक्त टिप्पणी गलत है?

संपादित:

MarkH's answer पढ़ने के बाद, मैं जाँच का एक सा था और पता चला कि NET अनुप्रयोगों बड़े पते के बारे में पता है जब 32-बिट में संकलित नहीं हैं और केवल एक 2GB वर्चुअल ऐड्रेस स्पेस संभाल कर सकते हैं मोड। (एक बड़े पते के बारे में पता झंडा चालू करने के लिए एक hack उपयोग कर सकते हैं लेकिन Markh के जवाब से पता चलता है कि .नेट फ्रेमवर्क के अंदर चेकों बातें क्योंकि पता स्थान केवल 2GB, नहीं 3GB माना जाता है टूट जाएगा।)

इसका मतलब है कि एक पॉइंटर के पास सभी सही आभासी मेमोरी पते हो सकते हैं (जहां तक ​​.NET Framework का संबंध है) 0x00000000 और 0x7FFFFFFF के बीच होगा। जब इस श्रेणी का अनुवाद int पर किया जाता है, तो कोई मान नकारात्मक नहीं होगा क्योंकि उच्चतम बिट सेट नहीं है। यह मेरी धारणा को मजबूत करता है कि IntPtr बनाम UIntPtr का उपयोग करने में कोई अंतर नहीं है। क्या मेरा तर्क सही है?

Fermat2357 ने बताया कि उपर्युक्त संपादन गलत है। के रूप में

private unsafe void* m_value; 

आप कर रहे हैं सही दोनों बस केवल बिट्स है कि एक पते का प्रतिनिधित्व प्रबंध

+0

यहां एक नज़र डालें। http://stackoverflow.com/questions/1320296/intptr-vs-uintptr –

+1

@ Fermat2357 हां, यही वह प्रश्न था जिसने मुझे एक नया प्रश्न लिखने के लिए प्रेरित किया। – xxbbcc

+0

मुझे लगता है कि आप सही हैं। बिल्कुल कोई फर्क नहीं पड़ता। एक 'हैंडल' संसाधन के लिए बस एक अद्वितीय संख्या है (निश्चित रूप से Win32 में इसे अक्सर स्मृति क्षेत्र में 32 बिट पॉइंटर के रूप में लागू किया जाता है)।हालांकि, 'IntPtr' किसी भी प्रकार की 32 बिट संख्या को एम्बेड करने में सक्षम है। UIntPtr में अंतर केवल इस संख्या की व्याख्या कुछ और नहीं है। समरूपता के लिए संकेत रैप करने के लिए एक नकली व्यर्थ प्रकार के होने - –

उत्तर

9

UIntPtr और IntPtr कार्यान्वित आंतरिक हैं।

एकमात्र चीज जहां मैं ओवरफ्लो समस्या के बारे में सोच सकता हूं वह है यदि आप पॉइंटर अंकगणित करने का प्रयास करते हैं। दोनों वर्ग ऑफसेट्स को जोड़ने और घटाने का समर्थन करते हैं। लेकिन इस मामले में इस तरह के एक ऑपरेशन के बाद द्विआधारी प्रतिनिधित्व ठीक होना चाहिए।

मेरे अनुभव से मैं UIntPtr भी पसंद करूंगा, क्योंकि मुझे एक हस्ताक्षर किए गए ऑब्जेक्ट के रूप में पॉइंटर पर लगता है। लेकिन यह प्रासंगिक नहीं है और केवल मेरी राय है।

यदि आप IntPtr या UIntPtr का उपयोग अपने मामले में करते हैं तो ऐसा कोई फर्क नहीं पड़ता है।

संपादित करें:

IntPtr सीएलएस अनुरूप क्योंकि वहाँ CLR जो अहस्ताक्षरित का समर्थन नहीं की चोटी पर भाषाओं कर रहे हैं।

+6

मुझे लगता है कि माइक्रोसॉफ्ट बहुत बेचैन किया ढांचे डिजाइन इस तरह का लगता है। उन्हें सिर्फ एक रैपर बनाया जाना चाहिए था और इसे सुरक्षित संरक्षित कहा जाना चाहिए था और हस्ताक्षरित/हस्ताक्षरित क्षेत्र में नहीं जाना चाहिए, जो बिल्कुल समझ में नहीं आता है। – xxbbcc

4

यह, वास्तव में, इसका तात्पर्य है कि इसमें कोई अंतर नहीं है (जब तक कोई मान को पूर्णांक में परिवर्तित करने की कोशिश नहीं करता)।

दुर्भाग्य से, ढांचा ठीक से ऐसा करने का प्रयास करता है (जब विशेष रूप से x86 के लिए संकलित किया जाता है)। IntPtr(long) कन्स्ट्रक्टर दोनों, और ToInt32() विधियों को checked अभिव्यक्ति में मान को int पर डालने का प्रयास किया गया है। फ्रेमवर्क डीबगिंग प्रतीकों का उपयोग करते हुए देखा गया कार्यान्वयन यहां दिया गया है।

public unsafe IntPtr(long value) 
    { 
     #if WIN32 
      m_value = (void *)checked((int)value); 
     #else 
      m_value = (void *)value; 
     #endif 
    } 

बेशक, जाँच की अभिव्यक्ति अपवाद फेंक देंगे अगर मूल्य सीमा से बाहर है। UIntPtr एक ही मान के लिए अतिप्रवाह नहीं है, क्योंकि यह इसके बजाय uint पर डालने का प्रयास करता है। , Int32 \ UInt32 (यानी, यह सब के बारे में कैसे संख्या व्याख्या करने के है।)

आमतौर पर, यह बात नहीं है जो आप चुनते हैं:

+0

मुझे आश्चर्य है अगर उस चेक की जगह में है क्योंकि उपयोगकर्ता वर्चुअल ऐड्रेस स्पेस 0x00000000 से 0x7FFFFFFF को जाता है। चूंकि बिट 31 मान्य वर्चुअल मेमोरी एड्रेस में सेट नहीं है, इसलिए 'चेक' रूपांतरण 32-बिट ओएस पर विफल नहीं होना चाहिए। मुझे यकीन नहीं है कि .NET समर्थन/3 जीबी है, क्योंकि यह वर्चुअल एड्रेस स्पेस बढ़ाता है। – xxbbcc

+0

दो सीटीओ हैं। एक 'सार्वजनिक IntPtr (लंबा मूल्य) 'और दूसरा' सार्वजनिक IntPtr (int मान) '। यह पूरी तरह से सामान्य (32 बिट विंडोज़ के लिए) है कि पहला सीटीआर केवल 64 बिट मान स्वीकार करता है जिसे बिना सटीक खोए 32 बिट तक जाया जा सकता है। –

+0

@ Fermat2357 हाँ, यह सही है, लेकिन 'checked' रूपांतरण, सटीक के नुकसान के बारे में नहीं है यह पता मान्य वैध पता सीमा के भीतर होना करने के बारे में है। सिद्धांत रूप में जांच 32-बिट सिस्टम पर विफल नहीं होनी चाहिए क्योंकि उपयोगकर्ता स्थान में उच्चतम बिट सेट नहीं किया जाना चाहिए। – xxbbcc

-1

IntPtr \ UIntPtr के बीच का अंतर मतभेद के बीच पाया रूप में ही है लेकिन, जैसा कि बताया गया है, कुछ मामलों में, यह आपको काटने के लिए वापस आ सकता है।

(मुझे यकीन नहीं है कि एमएस ने इंटप्राट (सीएलएस अनुपालन, आदि) के साथ क्यों शुरू किया है, स्मृति को डीडब्ल्यूओआर (यू 32) के रूप में संभाला जाता है, जिसका अर्थ है कि यह हस्ताक्षरित है, इस प्रकार, पसंदीदा विधि UIntPtr होना चाहिए, न कि ? IntPtr, दाएं)

भी: UIntPtr.Add()

मेरे लिए गलत लगता है, यह एक सूचक के रूप में एक UIntPtr लेता है, और एक ऑफसेट के लिए 'int'। (जब, मेरे लिए, 'यूंट' अधिक समझ में आता है। एक हस्ताक्षरित विधि पर हस्ताक्षरित मूल्य क्यों खिलाया जाता है, जब कोड की संभावना अधिक होती है, तो कोड को इसे 'यूंट' में हुड के नीचे डाला जाता है।/फेसपाल्म)

I व्यक्तिगत रूप से IntPtr पर UIntPtr को प्राथमिकता से पसंद करेंगे क्योंकि हस्ताक्षरित मान अंतर्निहित स्मृति के मानों से मेल खाते हैं जिनके साथ मैं काम कर रहा हूं। :)


Btw, मैं संभावना ऊपर अपने ही सूचक प्रकार (UInt32 का प्रयोग करके), स्मृति के साथ सीधे काम करने के लिए विशेष रूप से बनाया बनाने समाप्त कर देंगे। (मुझे लगता है कि UIntPtr सभी संभावित खराब मेमोरी मुद्दों, यानी 0xBADF00D, इत्यादि को पकड़ने वाला नहीं है, जो सीटीडी होने का इंतजार कर रहा है ... मुझे देखना होगा कि कैसे बनाया गया प्रकार उम्मीद है कि पहले चीजें हैंडल करती हैं, उम्मीद है कि एक शून्य \ शून्य चेक ठीक तरह से इस तरह की चीजें फ़िल्टर कर रहा है।)