这是第一个问题using c# pointers
的第二部分所以c#中的指针是“不安全的”,并且在IntPtr是托管对象时不由垃圾收集器管理。但为什么要使用指针呢?什么时候可以互换使用这两种方法?
答案 0 :(得分:8)
CLI区分托管和非托管指针。键入托管指针,运行时已知指向值的类型,并且只允许类型安全的分配。非托管指针只能在支持它们的语言中直接使用,C ++ / CLI就是最好的例子。
C#语言中非托管指针的等价物是IntPtr
。您可以使用强制转换来自由地来回转换指针。没有指针类型与它相关联,即使它的名称听起来像“指向int的指针”,它相当于C / C ++中的void*
。使用这样的指针需要pinvoke,Marshal类或强制转换为托管指针类型。
可以使用的一些代码:
using System;
using System.Runtime.InteropServices;
unsafe class Program {
static void Main(string[] args) {
int variable = 42;
int* p = &variable;
Console.WriteLine(*p);
IntPtr raw = (IntPtr)p;
Marshal.WriteInt32(raw, 666);
p = (int*)raw;
Console.WriteLine(*p);
Console.ReadLine();
}
}
请注意unsafe
关键字在此处的适用方式。你可以致电Marshal.WriteInt64(),你不会得到任何投诉。它会破坏堆栈帧。
答案 1 :(得分:7)
IntPtr
不能用作指针的替代。
IntPtr
只包含一个数值,因此您无法使用它来访问任何数据。由此得名;它是一个与指针大小相同的整数值。您需要将值转换为指针以访问它指向的数据,因此在不使用不安全代码的情况下无法访问数据。
另请注意,IntPtr
是一个结构,而不是一个对象,因此垃圾收集器根本不直接关注它。
答案 2 :(得分:6)
IntPtr
是一个托管对象,但它指向的对象仍然没有被垃圾回收。在C#中使用不安全的指针确实是你应该避免的。使用不安全指针的代码可能无法解释x86和x64系统之间内存地址的差异。它允许您轻松直接操作内存地址,这与IntPtr不同,因为您需要在指针和存储在此内存地址的实际结构之间进行编组。使用不安全的指针,您可以直接使用基础类型:这里是blog post我写的,说明了一个可能使用的不安全指针。另一个常见的例子是直接manipulating image pixels。
答案 3 :(得分:3)
取消引用IntPtr指向的数据就是将IntPtr的数字简单地粘贴到不安全的ptr的地址中,如下所示
unsafe{
IntPtr p = new MyStruct("fred");
myStruct * sptr;
sptr=p;
Console.WriteLine(*sptr->name);
}