zoukankan      html  css  js  c++  java
  • C#指针 常用手段

      指针真是一把神器啊!使用C#加指针来搞一下图像去色效果,整个过程低于15毫秒。而在不加指针的情况下却需要500毫秒。如果用C语言+指针来搞那就更快了。难怪操作系统用C#写不了。国庆这几天,除了和爸爸聊聊天,看看电影。没事就百度,谷歌,博客园搜一些C#指针的文章来看,但能找到的资料很少。

      我看了好几篇C#指针的文章后,遇到一个问题,C#和JAVA一样请了一个保姆,C#这个保姆比JAVA还能干,在C#几乎全部类都是托管的,而指针只能操作非托管的类,所以C#里的那些操作数据库的类,那些网络编程的类,那些文件处理的类,指针统统不能用。那该怎么办好呢?我百度了N次,找有没有办法把托管的类转换成非托管的,答案是NO。

      虽然这个问题我没找到解决,但不影响指针此刻在我心中肃立起的高大形象,我觉的它就是玄话武侠小说《诛仙》最强大的武器----诛仙剑。

      来看一下C#操作指针的一些常用手段

      C#要使用指针必需先把这个勾打上。

      常用代码我就直接COPY别人的了, 常用C#+指针原代码的出处是这篇文章《C# 指针复习示例

    View Code
    /// <summary>
        /// 指针,存储的是一个地址的整数。
        /// </summary>
        class Program
        {
            delegate void Methods();
    
            static void Main(string[] args)
            {
                Demo6();
                Console.ReadKey();
            }
    
            static void S(object o)
            {
                Console.WriteLine(o.ToString());
            }
    
            static void S(params object[] o)
            {
                foreach (object obj in o)
                    S(obj);
            }
    
            #region 指针简单示例
            unsafe static void Demo1()
            {
                int x = 10;//整数类型
                int* pX, pY;//指针坐标X、Y
                pX = &x;//取pX地址
                pY = pX;//将pX赋值给pY
    
                x = 15;
                *pX = 16;
                *pY = 17;
    
                S(x);
                S(*pX);//取得地址的内容
                S(*pY);
            }
            #endregion
    
            #region 指针的类型转换
            unsafe static void Demo2()
            {
                //NOTE:类型转换后,uint获得的是地址的十进制格式,并非获取地址的内容。
    
                int x = 10;//整数类型
                int* pX, pY;//指针坐标X、Y
                pX = &x;//取pX地址
                pY = pX;//将pX的地址赋值给pY
                uint ux = (uint)pX;//类型转换,获取地址的十进制
                int* pZ = (int*)ux;//类型转换,将地址赋值给pZ
    
                S(x);
                S(((uint)pX).ToString("x"));//十六进制内存地址
                S((uint)pY);//十进制内存地址
                S(ux);
                S((uint)pZ);//十进制内存地址
                S(*pZ);//输出地址的内容
            }
            #endregion
    
            #region DWORD内存块
            unsafe static void Demo3()
            {
                decimal m2 = 4.00m;
                byte b = 100;
                short s = 200;
                int i = 300;
                long l = 400;
    
                float f = 1.00f;
                double d = 2.00;
                decimal m = 3.00m;
    
                
                S(string.Format("byte:{0}", sizeof(byte)));
                S(string.Format("short:{0}", sizeof(short)));
                S(string.Format("int:{0}", sizeof(int)));
                S(string.Format("long:{0}", sizeof(long)));
                S(string.Format("float:{0}", sizeof(float)));
                S(string.Format("double:{0}", sizeof(double)));
                S(string.Format("decimal:{0}", sizeof(decimal)));
                S("");
                S("从高到矮……");
                S(string.Format("decimal:{0} +16  ↑", (uint)&m2));
                S(string.Format("byte:{0} +1  ↑", (uint)&b));
                S(string.Format("short:{0}  +2  ↑", (uint)&s));
                S(string.Format("int:{0}  +4  ↑", (uint)&i));
                S(string.Format("long:{0}  +8  ↑", (uint)&l));
                S(string.Format("float:{0}  +4  ↑", (uint)&f));
                S(string.Format("double:{0}  +8  ↑", (uint)&d));
                S(string.Format("decimal:{0}  +16  ↑", (uint)&m));
                S("有没有发现byte和short也是4个字节的内存块?因为.NET约定,最少要占用4个字节。");
            }
            #endregion
    
            #region 指针的运算
            unsafe static void Demo4()
            {
    
                byte b = 8;
                uint u = 3;
                double d = 10.0;
    
                byte* pByte = &b;
                uint* pUint = &u;
                double* pDouble = &d;
                S(string.Format("byte:{0}", (uint)pByte));
                S(string.Format("uint:{0}", (uint)pUint));
                S(string.Format("double:{0}", (uint)pDouble));
                pByte -= 3;
                ++pUint;
                S("\n");
                double* pDouble2 = pDouble + 4;
                S(string.Format("byte:{0}。old - 3 * 1", (uint)pByte));
                S(string.Format("uint:{0}。old + 4 * 1", (uint)pUint));
                S(string.Format("double2:{0}。pDouble + 4 * 8", (uint)pDouble2));
    
            }
            #endregion
    
            #region 结构指针
            unsafe static void Demo5()
            {
                
                MyStruct ms = new MyStruct();
                MyStruct* pms = &ms;
                (*pms).X = 5;//传统方式
                pms->Y = 10;//与C++雷同方式
    
                S(ms.X);
                S(ms.Y);
    
                int* X = &(pms->X);
                S(*X);
                *X = 15;
                S(*X);
                S(ms.X);
            }
    
            struct MyStruct
            {
                public int X;
                public int Y;
            }
            #endregion
    
            #region 类指针
            unsafe static void Demo6()
            {
                MyClass mc = new MyClass();
                //MyClass* pmc = &mc;//error,无法获取托管类型,因为它们嵌入一个对象。(结构是值类型)
                fixed (int* X = &(mc.X))
                fixed (int* Y = &(mc.Y))//*X和*Y固定或者fixed (int* X = &(mc.X), Q = &(mc.Y))。唯一限制,数据类型必须都是int*。
                {
                    *X = 5;
                    *Y = 6;
                    S(mc.X + "<-X  Y-> " + mc.Y);
                    fixed (int* Z = &(mc.Z))//*Z固定在X中。生命周期在于X、Y之间。
                    {
                        *Z = 7;
                        *X = 8;
                        *Y = 9;
                        S(mc.X + "<-X  Y-> " + mc.Y + "  Z->" + mc.Z);
                    }
                    *X = 10;
                    *Y = 11;
                    S(mc.X + "<-X  Y-> " + mc.Y);
                }
    
            }
            class MyClass
            {
                public int X;
                public int Y;
                public int Z;
            }
            #endregion

       另外,C#提供一个的关键字stackalloc用于申请堆栈内存。当函数执行完毕后,内存会被自动回收。使用这个堆内存的时候不必担心内存泄漏问题。

    View Code
        public class Program
        {
            static unsafe void Main(string[] args)
            {
                //分配p1一个100的大小
                int* p = stackalloc int[100];
                //赋值操作
                for (int i = 0; i < 100; i++)
                {
                    p[i] = i;
                }
                //测试内容
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine(*(p + i));
                }
                Console.ReadLine();
    
            }
        }

      最后有一篇《C# 指针之美》的文章,下面这些话摘抄自那里

      指针也可以操作非托管堆上的内存,如:

    IntPtr handle = System.Runtime.InteropServices.Marshal.AllocHGlobal(4);
                 Int32* p = (Int32*)handle;
                 *p = 20;
                 MessageBox.Show(p->ToString());
                 System.Runtime.InteropServices.Marshal.FreeHGlobal(handle);

      System.Runtime.InteropServices.Marshal.AllocHGlobal 用来从非托管堆上分配内存。System.Runtime.InteropServices.Marshal.FreeHGlobal(handle)用来释放从非托管对上分配的内存。这样我们就可以避开GC,自己管理内存了。

      如果使用非托管内存,建议用Dispose模式来管理内存,这样做有以下好处: 可以手动dispose来释放内存;可以使用using 关键字开管理内存;即使不释放,当Dispose对象被GC回收时,也会收回内存。

         下面是Dispose模式的简单例子:

    View Code
    View Code 
             public unsafe class UnmanagedMemory : IDisposable
             {
                 public int Count { get; private set; }
     
                 private byte* Handle;
                 private bool _disposed = false;
     
                 public UnmanagedMemory(int bytes)
                 {
                     Handle = (byte*) System.Runtime.InteropServices.Marshal.AllocHGlobal(bytes);
                     Count = bytes;
                 }
     
                 public void Dispose()
                 {
                     Dispose(true);
                     GC.SuppressFinalize(true);
                 }
     
                 protected virtual void Dispose( bool isDisposing )
                 {
                     if (_disposed) return;
                     if (isDisposing)
                     {
                         if (Handle != null)
                         {
                             System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)Handle);
                         }
                     }
                     _disposed = true;
                 }
     
                 ~UnmanagedMemory()
                {
                   Dispose( false );
                }
             }

      使用代码

           using (UnmanagedMemory memory = new UnmanagedMemory(10))
                {
                    int* p = (int*)memory.Handle;
                    *p = 20;
                    MessageBox.Show(p->ToString());
                }
  • 相关阅读:
    敏捷开发模式下的质量管理
    杨学明老师软件测试管理公开课将于2012年11月16日~17日在北京举办!
    杨学明老师为南京某机电企业成功举办两天IPD DRY RUN !
    软件测试管理公开课在北京成功举办!
    2012年12月4至6日,杨学明老师为中国科学院某研究所举办两天的软件项目管理和测试管理培训!
    杨老师“软件测试管理”公开课在北京成功举办!
    软件测试为什么失败?
    如何实现高效的产品测试管理杨学明
    杨学明老师软件测试管理公开课将于2012年9月21~22日在深圳举办!
    2011年9月23《软件测试管理》公开课,接受报名!
  • 原文地址:https://www.cnblogs.com/cxeye/p/2713364.html
Copyright © 2011-2022 走看看