2010-11-30 53 views
7

这是第一问题using c# pointersC#指针VS的IntPtr

所以在c#指针是“不安全”的和而一个IntPtr是被管理对象不会被垃圾收集器管理的第二部分。但为什么使用指针呢?什么时候可以交换使用两种方法?

+9

记住`IntPtr`仅仅是在.NET原始数据类型这是旨在举行一个地址。它基本上只是一个“int”,它是32位机器上的32位和64位机器上的64位。 “IntPtr”本身没有关于指针的具体内容。 – 2010-11-30 23:28:18

回答

7

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(),你什么都不会投诉。它破坏了堆栈帧。

5

IntPtr是一个托管对象,但它指向的对象仍然没有垃圾收集。在C#中使用不安全的指针确实是你应该避免的。使用不安全指针的代码可能不会考虑x86和x64系统之间的内存地址差异。它允许您直接操作内存地址,这与IntPtr不一样,因为您需要在指针和存储在此内存地址处的实际结构之间进行编组。使用不安全的指针可以直接使用底层的类型:这里是我写的一个blog post,说明了不安全指针的一种可能用法。另一个常见的例子是manipulating image pixels直接。

7

IntPtr不能用作指针的替代品。

IntPtr只包含一个数值,因此您不能使用它来访问任何数据。由此得名;它是一个与指针大小相同的整数值。您需要将该值转换为访问指向的数据的指针,因此如果不使用不安全的代码,则无法访问数据。

另外请注意IntPtr是一个结构,而不是一个对象,所以垃圾收集器根本就没有直接关心它。

+1

实际上有使用编组 – 2010-11-30 23:40:05

+2

@Ali Tarhini:这只是调用一种为您使用不安全代码的方法。关键是最终必须使用不安全的代码,否则无法访问数据。 – Guffa 2010-11-30 23:42:12

2

解引用指向的数据由IntPtr的是这仅仅粘附的IntPtr的数量为不安全的ptr的地址,如下