2009-02-26 13 views
20

सी # में, वहाँसी # स्मृति पते और चर

  1. के लिए एक रास्ता एक संदर्भ प्रकार चर में संग्रहीत स्मृति पता प्राप्त है?
  2. चर का मेमोरी पता प्राप्त करें?

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

int i; 
int* pi = &i; 
  • कैसे तुम बाहर पाई का हेक्स मान प्रिंट करूं?

उत्तर

13
# 2 के लिए

, & ऑपरेटर सी में के रूप में एक ही फैशन में काम करेंगे चर ढेर पर नहीं है, तो आप जब तुम इतना कचरा काम इसे नीचे पिन करने के लिए एक fixed कथन का उपयोग करना पड़ सकता है कलेक्टर इसे स्थानांतरित नहीं करता है, यद्यपि।

# 1 के लिए, संदर्भ प्रकार जटिल काम कर रहे हैं: आप एक GCHandle का उपयोग करना होगा, और संदर्भ प्रकार अर्थात है एक परिभाषित स्मृति लेआउट और copyable बिटवाइज़ जा, blittable हो गया है।

एक संख्या के रूप पते पर पहुंचने के लिए, आप सूचक प्रकार से IntPtr करने के लिए (एक पूर्णांक प्रकार सूचक के रूप में एक ही आकार के होने के लिए परिभाषित) वहाँ से uint या ulong (सूचक आकार के आधार पर पर कास्ट कर सकते हैं, और अंतर्निहित मशीन का)।

using System; 
using System.Runtime.InteropServices; 

[StructLayout(LayoutKind.Sequential)] 
class Blittable 
{ 
    int x; 
} 

class Program 
{ 
    public static unsafe void Main() 
    { 
     int i; 
     object o = new Blittable(); 
     int* ptr = &i; 
     IntPtr addr = (IntPtr)ptr; 

     Console.WriteLine(addr.ToString("x")); 

     GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); 
     addr = h.AddrOfPinnedObject(); 
     Console.WriteLine(addr.ToString("x")); 

     h.Free(); 
    } 
} 
+1

# 2, कि अच्छा है। लेकिन आप स्ट्रिंग के रूप में मेमोरी एड्रेस कैसे प्राप्त कर सकते हैं। मैं कहता हूं; int * pi = & i; मैं कंसोल का उपयोग करके इसे प्रिंट नहीं कर सकता।WriteLine (पीआई); मुझे कुछ उम्मीद है कि 0x0439ecc4 मुद्रित किया जाए। कोई सुराग? –

+0

कंसोल। राइटलाइन ("0x" + pi.ToString ("x") हेक्स मान –

+0

@ हैमिश, pi.ToString ("x") को संकलन त्रुटि को बढ़ाएगा। "ऑपरेटर"। प्रकार के संचालन पर लागू नहीं किया जा सकता 'int *' " –

5

नंबर 1 संभव नहीं है, आपके पास किसी प्रबंधित ऑब्जेक्ट के लिए पॉइंटर नहीं हो सकता है।

int* p = &myIntVariable; 

प्वाइंटर निश्चित रूप से होना जरूरी:

GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned); 
IntPtr pointer = GCHandle.ToIntPtr(handle); 
string pointerDisplay = pointer.ToString(); 
handle.Free(); 

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

+0

कमजोर, कोड स्ट्रिंग स्ट्र =" हैलो "के साथ संकलित क्यों नहीं हो सकता; स्ट्रिंग * पीआरटी = स्ट्र; कोई विचार? –

+0

मेरा बुरा, वास्तव में यह बिल्कुल संभव नहीं है। आप किसी प्रबंधित ऑब्जेक्ट के लिए पॉइंटर नहीं हो सकता है, आपको एक इंटिप्टर का उपयोग करना होगा। – Guffa

+5

डाउनवोट क्यों? यदि आप यह नहीं कहते कि यह क्या है जो आपको पसंद नहीं है, तो यह व्यर्थ है ... – Guffa

2

सबसे सही ढंग से अपने प्रश्न का उत्तर करने के लिए:

# 1 संभव थोड़ा मुश्किल है, लेकिन, और केवल डिबगिंग कारणों के लिए किया जाना चाहिए:

object o = new object(); 
TypedReference tr = __makeref(o); 
IntPtr ptr = **(IntPtr**)(&tr); 

यह किसी भी वस्तु के लिए काम करता है और वास्तव में आंतरिक रिटर्न स्मृति में वस्तु के लिए सूचक। याद रखें कि जीसी की वजह से पता किसी भी पल में बदल सकता है, जो स्मृति में वस्तुओं को स्थानांतरित करना पसंद करता है।

# 2 पॉइंटर्स ऑब्जेक्ट्स नहीं हैं और इस प्रकार उनके लिए ToString का उत्तराधिकारी नहीं है। तुम इतनी तरह IntPtr सूचक कास्ट करने के लिए है:

Console.WriteLine((IntPtr)pi); 
संबंधित मुद्दे