一、unsafe
如果因需要想在c#中使用指针,那么unsafe便是一个通道(当然在使用前,需在项目属性的生成选项中,选择“允许不安全代码”)。
example 1:
a) 创建项目,项目属性->生成->选择“允许不安全代码”
b) 编写代码
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- namespace ConsoleDll
- {
- //此处为c++动态库的调用,因DllC++.dll是示例测试文件,为不影响代码演示,此处屏蔽
- //public class Code
- //{
- // [DllImport("DllC++.dll")]
- // public unsafe static extern int Add(int a, int* b);
- //}
- class Program
- {
- public unsafe static int Add(int a, int* b)//此处使用指针,需要加入非安全代码关键字unsafe
- {
- return a + *b;
- }
- static void Main(string[] args)
- {
- unsafe//此代码块为非安全代码,可以使用指针
- {
- int resDll,resInner, a;
- int* b;//如果在安全代码条件下,编译不会通过对指针的定义
- a = 1;
- b = &a;
- // resDll = Code.Add(a, b);
- resInner = Add(a,b);
- }
- }
- }
- }
上面代码简单的示范了何种情况下可以使用指针。
二、fixed
fixed其实是在非安全代码下用到才会有意义的。因为他负责对指针所指向的“动态分配内存的对象或对象中的成员”简称“对象”进行锁定(之所以要锁定,是因为即使在非安全代码模式下,这些对象一样的使用CLR的代码托管,这样的话,很可能造成对象的地址变动,就是因为CLR对资源重新分配的不确定性,假使指针在未完成对对象的操作时,对象地址变动,那么指针指向的地址就会出现混乱,很可能造成内存泄漏甚至系统崩溃。如果使用fixed进行锁定,那么只有在执行完fixed模块后,指针所指向的对象才能被移动)。
CLR对资源重新分配后,变量对象的值是保持不变的,但是变量对象的内存地址可能变了。所以,指针变量的值是不会变的,但是当该指针所指向的对象的地址发生了变化的话,那么该指针可能会指到别的位置去了。即造成非法访问等混乱情况。
example 2:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- namespace ConsoleDll
- {
- public static int Add(int[] a,int b)
- {
- unsafe
- {
- fixed (int* pa = a)//此处将锁住a,使得在fixed操作块内,a不会被CLR移动
- {
- return *pa + b;
- }
- }
- }
- static void Main(string[] args)
- {
- int[] a = new int[1];
- a[0] = 1;
- int b = 2;
- int res = Add(a,b);
- }
- }
- }
上述代码需注意的是:指针变量pa的值(数组a的首地址)也是被固定了的(固定指向a),所以不能将别的地址赋值给pa。但是可以修改pa所指的对象a的值。