C# 与 C++强强联合--C#中的指针
非常的不好意思,距离上次随笔C# 与 C++强强联合已经过去快1个月了。承诺大家的C#指针和A*算法迟迟未上。为表歉意献上美女一枚
哈哈。流口水了吧
话归正题。
一、指针是什么呢?
指针就是指针嘛!这是我的第一想法。因为我觉得这样解释已经很明确了。要更明确的话,指针是对系统使用的变量、方法在内存上的一个页签,通过指针就能找到他们。
二、C#指针有那些应用?
int* p表示一个变量内存地址,delegate通常用于表示对方法的引用。
三、应用
1、*
unsafe static void Main(string[] args) { int* pa, pb; int a = 1, b = 2; pa = &a; pb = &b; Console.WriteLine(pa[0] + pb[0]); Console.ReadLine(); }
代码不解释,会不会开发的我想都懂。但是我们是C#下使用指针需要注意些什么呢?
3.1、C#默认是不允许使用指针的,因为她任务这会增加程序的不安全性,需要我们设置下
勾上这个,然后使用的地方需要添加unsafe。
3.2、C#有个垃圾回收机制,为我们开发节约了很多时间,不用去管内存的释放。但是我们使用指针会遇到什么样的问题呢?我们系统变量可以分为活动变量和固定变量,固定的变量永久的存在并不会被GC的操作影响。(例如局部变量,值参数和间接指针)活动的变量会被GC重新分配位置或是释放(例如对象中的字段,基础数据数组)。如果我们使用的是活动变量这个这个会让我们的指针指的实际地址内容发生变化。这样我们需要fixed
fixed 语句禁止垃圾回收器重定位可移动的变量
Point pt = new Point(); fixed (int* p = &pt.x) { *p = 1; }
3.3、以前有人说C#分配数组的不是连续的内存块,今天也试了下,纯粹扯蛋。
int[] array = new int[100]; for (int i = 0; i < 100; i++) { Console.WriteLine(Marshal.UnsafeAddrOfPinnedArrayElement(array, i).ToString()); } Console.ReadLine();
int是32位,使用4个个字节,从上面的地址看下,所以啊,是完全连接的嘛!
3.4、暂时不知道写什么,大家补充啊!....
二、delegate
public delegate int _DSum(int a, int b); static void Main(string[] args) { _DSum sum = Sum; Console.WriteLine(sum(1, 2)); Console.ReadLine(); } public static int Sum(int a, int b) { return a + b; }
看上面这段代码就发现啦,我把Sum方法给_DSum的变量小sum了。这样就可以通过小sum,直接调用大Sum啦。这就是我说的方法的指针。
常用使用情况有
1、事件
class Program { unsafe static void Main(string[] args) { Calculate calculate = new Calculate(); //实例Calculate
calculate._ESum += new Calculate._DSum(calculate__ESum); //创建_ESum事件的监听,怎么监听的呢?通过Calculate的_DSum委托,触发时执行_DSum指向的方法calculate__ESum
Console.WriteLine(calculate.Sum(1, 2)); Console.ReadLine(); } static void calculate__ESum(int a, int b) { Console.Write("{0}+{1}=", a, b); } } public class Calculate { public delegate void _DSum(int a, int b); public event _DSum _ESum; public int Sum(int a, int b) { _ESum(a, b); return a + b; } }
2、UI处理
private unsafe void button1_Click(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(Bind));//创建个新线程 t.Start(); //启动线程 } private void Bind() { for (int i = 0; i < 10; i++) { DShow dShow = show; //把方法show委托给dShow this.BeginInvoke(dShow, i); //在创建textBox1的句柄上去执行dShow Thread.Sleep(800); } } private delegate void DShow(int num); private void show(int num) { textBox1.Text = num.ToString(); }
解释下为什么在创建textBox1的句柄上去执行dShow,Window是一个消息机制的操作系统,怎么说呢!就是你要执行的命名不是立马执行(当然了也可以马上执行,想游戏类不然都延迟卡死,不没法玩了)而是放到一个待执行命令的消息队列中,某个进程的一系列任务不是一个一个的去执行的,而且有线程池,可以同时并行去执行。我们的UI有个线程。为了不卡住UI,我们需要创建个新的线程。新的线程就直接去填值也是不行,线程间有安全机制。不能你操作我的东西,我操作别人的东西,这样就需要自己操作自己的。所以使用BeginInvoke。就算是自己操作自己的,我也可以等待你执行完了再执行下一个也可以不等啊。这样就有的BeginInvoke和Invoke区别了。
(*^__^*) 嘻嘻,写了半天了,中间还去开了会打了下酱油。今天先这样吧!不好的大家见谅,勇敢的指出来