以下总结C#指针操作的知识点
一、unsafe的用法
1、C#使用指针首先要用unsafe声明
unsafe声明可以用在方法或代码块
(1)方法声明为unsafe
static unsafe void Main(string[] args)
{
int var = 20;
int* p = &var;
Console.WriteLine("Data is: {0} ", var);
Console.WriteLine("Address is: {0}", (int)p);
Console.ReadKey();
}
(2)将代码块声明为unsafe
public static void Main(string[] args)
{
unsafe
{
int var = 10;
int* p = &var;
Console.WriteLine("var:{0}", var);
//可以使用 ToString() 方法检索存储在指针变量所引用位置的数据
Console.WriteLine("var:{0}", p->ToString());
Console.WriteLine("Address:{0}", (int)p);
}
Console.ReadKey();
}
2、使用unsafe时,首先要设置编译器,允许编译不安全代码
项目文件-属性-生成-勾选不安全代码
二、C#指针操作
1、fixed
fixed 语句可防止垃圾回收器重新定位可移动的变量。 fixed 语句仅允许存在于不安全的上下文中。 还可以使用 fixed 关键字创建固定大小的缓冲区。
fixed 语句将为托管变量设置一个指针,并在该语句的执行过程中“单边锁定”该变量。 仅可在 fixed 上下文中使用指向可移动托管变量的指针。 如果没有 fixed 上下文,垃圾回收可能会不可预测地重定位变量。 C# 编译器只允许将指针分配给 fixed 语句中的托管变量。
2、对C#的数组用指针进行操作
C#的数值是引用类型,其中C#的指针类型不允许是引用类型
const int size = 2048 * 300 * 2;
int line = 300;
//int d = 0;
short[] genePic = new short[size];
for (int i = 0; i < size; i++)
{
genePic[i] = (short)i;
}
//取数组genePic的地址,并将其传给ptr
IntPtr ptr;
unsafe
{
void* p;
fixed (short* pc = genePic)
{
p = (void*)pc;
ptr = new IntPtr(p);
}
}
3、C# IntPtr类型
IntPtr类型称为“平台特点的整数类型”用于表示指针或句柄的平台特定类型。
IntPtr类型设计为一个整数,其大小是特定于平台的。 也就是说,此类型的实例应该是32位硬件和操作系统上的32位,以及64位硬件和操作系统上的64位。
IntPtr类型具体用法参考如下:
https://docs.microsoft.com/zh-cn/dotnet/api/system.intptr?view=netframework-4.8
4、Marshal类
Marshal类提供了一个方法集合,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。
(1)根据指针读取指针的内容
//将指针IntPtr ptr指向的内容拷贝到数组genePic2
short[] genePic2 = new short[size];
for (int i = 0; i < size; i++)
{
genePic2[i] = Marshal.ReadInt16(ptr+2*i);//读取指针指向的内容
}
(2)将 16 位整数值写入非托管内存
static void WriteInt16(IntPtr ptr, short val);
ptr 非托管内存中要写入的地址。
Int16 要写入的值。
Marshal类具体用法参考如下:
三、常用类型转换总结
1、C# 字符串转C char *
string s_filePath = "test.txt";
//字符串转指针
ntPtr p_filePath = Marshal.StringToCoTaskMemAnsi(s_filePath);