什么是一个IntPtr究竟是什么?

通过使用IntelliSense并查看其他人的代码,我遇到了这种IntPtrtypes; 每次需要使用我只是把nullIntPtr.Zero并发现大部分function工作。 究竟是什么以及何时/为什么使用?

这是一个“本地(特定平台)大小的整数”。 它在内部表示为void*但是作为整数暴露。 只要需要存储非托pipe指针并且不想使用unsafe代码,就可以使用它。 IntPtr.ZeroNULL (空指针)。

这是一个足够大的值types来存储本地或不安全代码中使用的内存地址,但不能直接用作安全托pipe代码中的内存地址。

您可以使用IntPtr.Size来确定您是在32位还是64位进程中运行,因为它们分别是4或8个字节。

直接解释

IntPtr是一个与指针大小相同的整数

您可以使用IntPtr将指针值存储在非指针types中。 这个特性在.NET中很重要,因为使用指针是非常容易出错的,因此在大多数情况下是非法的。 通过允许将指针值存储在“安全”数据types中, 不安全的代码段之间的pipe道可以用更安全的高级代码实现 – 甚至是不直接支持指针的.NET语言。

IntPtr的大小是平台特定的,但是这个细节很less需要考虑,因为系统会自动使用正确的大小。

名字“IntPtr”令人困惑 – 像Handle这样的东西可能更合适。 我最初的猜测是“IntPtr”是一个指向一个整数。 IntPtr的MSDN文档进入了一些晦涩的细节,没有提供太多的名字的含义的见解。

另一个angular度

一个IntPtr是一个有两个限制的指针:

  1. 它不能直接解除引用
  2. 它不知道它指向的数据的types。

换句话说,一个IntPtr就像一个void* – 但是有了额外的function,它可以(但不应该)用于基本的指针运算。

为了解引用一个IntPtr ,你可以把它转换成一个真正的指针(一个只能在“不安全的”上下文中执行的操作),或者你可以把它传递给一个辅助例程,比如InteropServices.Marshal类提供的那些例程。 使用Marshal课给出了安全的幻觉,因为它不需要你在一个明确的“不安全”的情况下。 但是,它并没有消除使用指针所固有的崩溃风险。

这是一个例子:

我正在写一个C#程序,与高速摄像头连接。 相机有自己的驱动程序,可以自动获取图像并将其加载到计算机的内存中。

所以当我准备将最新的图像带入我的程序中时,摄像机驱动程序为我提供了一个IntPtr,以便将图像存储在物理内存中,因此我不必浪费时间/资源创build另一个图像内存块来存储已经在内存中的图像。 IntPtr只是显示图像已经在哪里。

MSDN告诉我们:

IntPtrtypes被devise为一个大小是平台特定的整数。 也就是说,这种types的实例有望在32位硬件和操作系统上为32位,在64位硬件和操作系统上为64位。

IntPtrtypes可以被支持指针的语言所使用,也可以被用作在不支持指针的语言之间引用数据的常用方法。

IntPtr对象也可以用来保存句柄。 例如,IntPtr的实例被广泛用于System.IO.FileStream类来保存文件句柄。

IntPtrtypes是CLS兼容的,而UIntPtrtypes不是。 在公共语言运行库中只使用IntPtrtypes。 UIntPtrtypes主要是为了维持IntPtrtypes的结构对称性。

http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx

那么这是处理IntPtr的MSDN页面 。

第一行是:

用于表示指针或句柄的平台特定types。

至于指针或句柄是什么页面进行说明:

IntPtrtypes可以被支持指针的语言所使用,也可以被用作在不支持指针的语言之间引用数据的常用方法。

IntPtr对象也可以用来保存句柄。 例如,IntPtr的实例被广泛用于System.IO.FileStream类来保存文件句柄。

一个指针是一个内存区域的引用,它包含你感兴趣的一些数据。

句柄可以是对象的标识符,当双方都需要访问该对象时,该句柄在方法/类之间传递。

什么是指针?

在所有语言中,指针是一种存储内存地址的variables,您可以要求它们告诉您指向的地址或指向的地址

指针可以被认为是一种书签。 除了用于快速跳转到书中的页面之外,使用指针来跟踪或映射内存块。

设想你的程序内存就像一个65535字节的大数组。

指针乖乖点

指针每个都记住一个内存地址,因此它们都指向内存中的一个地址。

作为一个组,指针记住和调用内存地址,遵守你的每一个命令都是令人厌恶的。

你是他们的国王。

在C#中的指针

特别是在C#中,指针是一个整数variables,它存储0到65534之间的内存地址。

同样特定于C#,指针的types为int,因此被签名。

您不能使用负数地址,也不能使用65534以上的地址。任何尝试这样做都会抛出System.AccessViolationExceptionexception。

称为MyPointer的指针是这样声明的:

int * MyPointer;

C#中的一个指针是一个int,但C#中的内存地址从0开始,最大可扩展到65534。

尖锐的东西应该特别小心处理

“不安全”这个词为了吓倒你,而且有一个很好的理由:指针是尖尖的东西,而尖锐的东西,例如剑,斧头,指针等,应该特别小心处理。

指针给程序员严格控制系统。 所以犯错可能会有更严重的后果。

为了使用指针,必须在程序的属性中启用不安全的代码,指针必须专门用于标记为不安全的方法或块。

一个不安全的块的例子

 unsafe { // Place code carefully and responsibly here. } 

如何使用指针

当variables或对象被声明或实例化时,它们被存储在内存中。

  • 通过使用*符号前缀声明一个指针。

int *MyPointer;

  • 要获取variables的地址,请使用&符号前缀。

MyPointer = &MyVariable;

一旦一个地址被分配给一个指针,以下情况适用:

  • 没有*前缀指向被指向的内存地址为int。

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • 用*前缀来获取存储在指向内存地址的值。

"MyPointer is pointing at " + *MyPointer;

由于指针是一个包含内存地址的variables,因此该内存地址可以存储在一个指针variables中。

指针的例子正在谨慎而负责任地使用

  public unsafe void PointerTest() { int x = 100; // Create a variable named x int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer. } 

注意指针的types是一个int。 这是因为C#将内存地址解释为整数(int)。

为什么它是int而不是uint?

没有什么好的理由。

为什么使用指针?

指针很有趣。 有了这么多的计算机被内存控制,指针使程序员能够更好地控制程序的内存。

内存监视。

使用指针读取内存块,并监视指向值随着时间的变化。

以负责任的方式更改这些值,并跟踪您的更改如何影响您的计算机。