नेट पर कई उदाहरण हैं कि byte[] या int[,] के लिए पॉइंटर कैसे प्राप्त करें, यानी जब आप ऐरे के तत्व प्रकार और रैंक को ठीक से जानते हैं। लेकिन जेनेरिक Array के लिए पॉइंटर कैसे प्राप्त करें?

यहां मुख्य समस्या यह है कि मुझे अग्रिम में रैंक का पता नहीं है। मैं तत्व प्रकार भी नहीं जानता लेकिन मुझे पता है कि केवल आदिम संख्यात्मक प्रकार (मेरे मामले में) हो सकते हैं, इसलिए मैं इससे निपटने के लिए कुछ अतिरिक्त if टाइप कर सकता हूं।

पृष्ठभूमि: मैं यह समाधान करना चाहूंगा https://stackoverflow.com/a/52750659/6734314 अधिक सामान्य -- अपने वर्तमान स्वरूप में यह केवल double[,] के साथ काम करता है इसलिए क्लासिक रैंक+प्रकार दिया जाता है:

double[,] doubles =  {
     { 1, 2, 3, 4 },
     ...
};
fixed (double* p = doubles)
{
  ...

पहला प्रयास

ओलिवियर उत्तर से, सभी गलतियाँ मेरी हैं।

Array data = new float[,] { { 4, 2 }, { 77, 3 } };
var reference = __makeref(data);
IntPtr pointer = **(IntPtr**)(&reference);

float* ptr = (float*)pointer.ToPointer();
{
  for (int i = 0; i < data.LongLength; ++i)
    Console.WriteLine(ptr[i]);
}
2
astrowalker 15 सितंबर 2020, 12:45

4 जवाब

सबसे बढ़िया उत्तर

मुझे लगता है कि मुझे यह मिल गया है, कृपया टिप्पणी करें कि क्या आपको कुछ बहुत नाजुक/संदिग्ध मिला है:

Array data = new float[,] { { 4, 2 }, { 77, 3 } };
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
  IntPtr address = handle.AddrOfPinnedObject();

  float* ptr = (float*)address.ToPointer();
  for (int i = 0; i < data.LongLength; ++i)
    Console.WriteLine(ptr[i]);
}
finally
{
  handle.Free();
}
1
astrowalker 15 सितंबर 2020, 15:34

संयोजन:

सी # में किसी वस्तु का मेमोरी पता

और

मैं सी # में एक सूचक पता कैसे प्रदर्शित कर सकता हूं?

लिखना:

Array array = Array.CreateInstance(typeof(int), 10);
unsafe
{
  var reference = __makeref(array);
  var pointer = **(IntPtr**)( &reference );
  Console.WriteLine("0x{0:x}", (ulong)&reference);
  Console.WriteLine("0x{0:x}", (long)&reference);
  Console.WriteLine("0x{0:x}", (ulong)pointer);
  Console.WriteLine("0x{0:x}", (long)pointer);
}

आउटपुट:

0x8cb87af070
0x8cb87af070
0x1a9c1c46290
0x1a9c1c46290

ऐरे क्लास का सोर्स कोड

3
Olivier Rogier 15 सितंबर 2020, 13:00

यदि डेटा हमेशा एक ही आकृति (उदाहरण के लिए, 2D आयताकार सरणी) है, लेकिन संभावित रूप से भिन्न प्रकार है, तो आप शायद T : unmanaged बाधा का उपयोग कर सकते हैं और fixed कीवर्ड:

    static void Main()
    {
        // sample taken from comtrade91.pdf section 6.6
        var data = new float[,] { { 4, 2 }, { 77, 3 } };
        ShowAddressAndData(data);
    }
    static unsafe void ShowAddressAndData<T>(T[,] data) where T : unmanaged
    {
        fixed(T* ptr = data)
        {
            Console.WriteLine((IntPtr)ptr);
            for (int i = 0; i < data.Length; i++)
            {
                Console.WriteLine(ptr[i]);
            }
        }
    }
    // this extra method just to show that we can overload on dimension
    static unsafe void ShowAddressAndData<T>(T[] data) where T : unmanaged
    {
        fixed (T* ptr = data)
        {
            Console.WriteLine((IntPtr)ptr);
            //..
        }
    }
2
Marc Gravell 15 सितंबर 2020, 15:27

मेरे पास आपके लिए एक बहुत ही आसान उपाय है

इस लिंक पर जाएं और वह लिंक।

और फिर आप अपने कोड में लिखेंगे:

Array tableArray = Array.CreateInstance(typeof(int), 10);
unsafe
{
  var ref = __makeref(tableArray);
  var p = **(IntPtr**)( &ref);
  Console.WriteLine("0x{0:x}", (ulong)&ref);
  Console.WriteLine("0x{0:x}", (long)&ref);
  Console.WriteLine("0x{0:x}", (ulong)p);
  Console.WriteLine("0x{0:x}", (long)p);
}

और आपके आउटपुट इस तरह होंगे:

  • 0x8cb87af070
  • 0x8cb87af070
  • 0x1a9c1c46290
  • 0x1a9c1c46290

सरणी वर्ग

-4
expertDev 15 सितंबर 2020, 13:11