c#pointers vs IntPtr

时间:2010-11-30 23:17:58

标签: c# .net pointers

这是第一个问题using c# pointers

的第二部分

所以c#中的指针是“不安全的”,并且在IntPtr是托管对象时不由垃圾收集器管理。但为什么要使用指针呢?什么时候可以互换使用这两种方法?

4 个答案:

答案 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);

}