zoukankan      html  css  js  c++  java
  • C#指针操作Marshal实例

            static void Main(string[] args)
            {
                byte[] a = new byte[]{0,0,0,0};
                byte[] b = new byte[] {1,2,3,4};
                IntPtr pt = Marshal.AllocHGlobal(a.Length);
                //从source数组的startIndex下标开始复制length个对象到ptr;
                Marshal.Copy(b,0,pt+0,b.Length);
                //从ptr复制length个对象到目标数组的,从目标数组的startIndex开始写入。
                Marshal.Copy((pt+1),a,1,2);
                unsafe
                {
                    byte* pb = (byte*) pt;
                    for (int i = 0; i < a.Length; i++)
                    {
                        Console.WriteLine("/b:"+(*pb++) + "/a:" + a[i]);
                    }
                }
                //释放非托管内存;
                Marshal.FreeHGlobal(pt);
    
                byte[] arBt = new byte[]{200,0,20,30,40,50,60,70,80,90,11,12,13,14,0x0f,199};
                IntPtr ptr = Marshal.AllocHGlobal(arBt.Length);
                //写入数据;
                Marshal.Copy(arBt, 0, ptr, arBt.Length);
                short[] arSt = new short[arBt.Length / sizeof(short)];
                int[] arInt = new int[arBt.Length / sizeof(int)];
                //复制为short数据;
                Marshal.Copy(ptr, arSt, 0, arSt.Length);
                //调整数据 此时arSt不变 下面的arInt改变;
                Marshal.WriteByte(ptr, 1, 9);
                Marshal.WriteByte(ptr, 10, (byte)(Marshal.ReadByte(ptr,10)*9));
                //复制为int数据;
                Marshal.Copy(ptr, arInt, 0, arInt.Length);
                for (int i = 0; i < arBt.Length; i++)
                {   
                    Console.Write(arBt[i] + "-");
                }
                Console.WriteLine();
                for (int i = 0; i < arBt.Length; i++)
                {   
                    Console.Write(Marshal.ReadByte(ptr,i) + "-");
                }
                Console.WriteLine();
                unsafe
                {  //获取指定数组中指定索引处的元素的地址
                    short* ps = (short*)Marshal.UnsafeAddrOfPinnedArrayElement(arSt, 0);
                    byte[] tmp0 = BitConverter.GetBytes(*ps);
                    Console.WriteLine(*ps+ "/" + (ushort)*ps+ ",byte>>>&0=" + tmp0[0] + ",&1=" + tmp0[1]);
              //获取指定数组中指定索引处的元素的地址
                    int* pi = (int*)Marshal.UnsafeAddrOfPinnedArrayElement(arInt, 0);
                    byte[] tmp1 = BitConverter.GetBytes(*pi);
                    Console.WriteLine(*pi + "/" + (uint)*pi + ",byte>>>&0=" + tmp1[0] + ",&1=" + tmp1[1] +",&2="+ tmp1[2] + ",&3=" + tmp1[3]);
    
                    Console.WriteLine("-----short 2 byte-----");
                    for (int i = 0; i < arSt.Length; i++)
                    {
                        byte[] tmp = BitConverter.GetBytes(arSt[i]);
                        Console.WriteLine(arSt[i] + "/" + (ushort)arSt[i] + ",byte>>>&0=" + tmp[0] + ",&1=" + tmp[1]);
                    }
                    Console.WriteLine("-----int 2 byte-----");
                    for (int i = 0; i < arInt.Length; i++)
                    {
                        byte[] tmp = BitConverter.GetBytes(arInt[i]);
                        Console.WriteLine(arInt[i] + "/" + (uint)arInt[i] + ",byte>>>&0=" + tmp[0] + ",&1=" + tmp[1] + ",&2=" + tmp[2] + ",&3=" + tmp[3]);
                    }
                }
                Marshal.FreeHGlobal(ptr);
           unsafe
                {
                    Test tt = new Test();
                    tt.t1 = 100;
                    tt.t2 = true;
                    tt.t3 = 6666;
                    tt.t4 = 666666;
                    tt.t6 = false;
                    string s = "ABCD大师0X00";
                    char[] chs = s.ToCharArray();
                    char* block = stackalloc char[100];
                    fixed (char* cpt = chs)
                    {
                        for (int i = 0; i < chs.Length; i++)
                        {
                            tt.t5[i] = *(cpt + i);
                            block[i] = *(cpt + i);
                        }
                        Console.WriteLine(new string(tt.t5));
                    }
                }
            }
            [StructLayout(LayoutKind.Sequential, Pack = 4)]
            public unsafe struct Test
            {
                public byte t1;
                public bool t2;
                public ushort t3;
                public int t4;
                //固定大小的缓冲区
                public fixed char t5[100];
                public bool t6;
            }

    //----------------------------------

    通过上面的例子,我们可以看出,使用C#指针操作内存,非常方便。使用Marshal我们可以获得非托管内存的指针IntPtr。该指针我们可以强制转换为

    sbytebyteshortushortintuintlongulongcharfloatdoubledecimalbool的类型指针。之后我们可以Copy,Read ,Write等操作内存。

    同C++一样我们获得的指针可以通过指针运算符 *,->,&,++,--进行指定内存的数据和位移操作。也可以通过Marshal,将我们的byte类型数据进行类型转换操作。

    Marshal类提供的转换函数功能之强大。

    可参阅https://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.marshal_methods%28v=vs.80%29.aspx;

     

  • 相关阅读:
    C++中智能指针的设计和使用
    [转]C++ 智能指针详解
    C++ const 常量和常指针
    深入理解C++中的mutable关键字
    C++ 静态常量
    BZOJ 1875: [SDOI2009]HH去散步
    BZOJ 1024: [SCOI2009]生日快乐
    BZOJ 1059: [ZJOI2007]矩阵游戏
    bzoj 1833: [ZJOI2010]count 数字计数
    LUOGU P2587 [ZJOI2008]泡泡堂
  • 原文地址:https://www.cnblogs.com/2Yous/p/4897812.html
Copyright © 2011-2022 走看看