183

通过使用 IntelliSense 并查看其他人的代码,我遇到了这种IntPtr类型;每次需要使用它时,我都会简单地放置nullIntPtr.Zero发现大多数功能都可以工作。它到底是什么以及何时/为什么使用它?

4

8 回答 8

170

这是一个“本机(特定于平台)大小的整数”。它在内部表示为void*但公开为整数。您可以在需要存储非托管指针并且不想使用unsafe代码时使用它。IntPtr.Zero是有效NULL的(一个空指针)。

于 2009-07-18T18:15:06.053 回答
73

它是一种足够大的值类型,可以存储在本机或不安全代码中使用的内存地址,但不能直接用作安全托管代码中的内存地址。

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

于 2009-07-18T18:15:41.793 回答
54

这是一个例子:

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

因此,当我准备好将最新图像带入我的程序以使用时,相机驱动程序为我提供了一个 IntPtr,该图像已存储在物理内存中,因此我不必浪费时间/资源创建另一个内存块来存储已经在内存中的图像。IntPtr 只是告诉我图像已经在哪里。

于 2009-07-18T19:24:36.973 回答
43

直接的解释

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

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

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

“IntPtr”这个名字令人困惑——类似的东西Handle可能更合适。我最初的猜测是“IntPtr”是一个指向整数的指针。IntPtr的MSDN 文档涉及到一些神秘的细节,但没有提供太多关于名称含义的见解。

另一种观点

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

  1. 不能直接取消引用
  2. 它不知道它指向的数据的类型。

换句话说, anIntPtr就像 a void*-- 但具有可以(但不应该)用于基本指针运算的额外功能。

为了取消引用 an IntPtr,您可以将其强制转换为真正的指针(只能在“不安全”上下文中执行的操作),也可以将其传递给辅助例程,例如InteropServices.Marshal类提供的那些。使用Marshal该类会产生安全的错觉,因为它不需要您处于明确的“不安全”上下文中。但是,它并没有消除使用指针固有的崩溃风险。

于 2009-11-01T01:47:34.547 回答
22

什么是指针?

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

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

想象一下您的程序的内存就像一个 65535 字节的大数组。

指针乖乖的指向

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

作为一个群体,指针会记住和回忆内存地址,服从你的每一个命令。

你是他们的王。

C#中的指针

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

同样特定于 C#,指针是 int 类型,因此是有符号的。

但是,您不能使用负编号地址,也不能访问高于 65534 的地址。任何这样做的尝试都会抛出 System.AccessViolationException。

一个名为MyPointer的指针声明如下:

int *MyPointer;

C# 中的指针是 int,但 C# 中的内存地址从 0 开始并延伸到 65534。

处理尖锐的事情时应格外小心

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

指针使程序员可以严格控制系统。因此,所犯的错误可能会产生更严重的后果。

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

不安全块的示例

unsafe
{
    // Place code carefully and responsibly here.

}

如何使用指针

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

  • 使用 * 符号前缀声明指针。

int *MyPointer;

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

MyPointer = &MyVariable;

将地址分配给指针后,将应用以下内容:

  • 如果没有 * 前缀,则表示指向的内存地址为 int。

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

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

"MyPointer is pointing at " + *MyPointer;

由于指针是一个保存内存地址的变量,所以这个内存地址可以存储在指针变量中。

谨慎和负责任地使用指针的示例

    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.

    }

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

为什么是int而不是uint?

没有充分的理由。

为什么要使用指针?

指针很有趣。由于计算机的大部分内容由内存控制,因此指针使程序员能够更好地控制其程序的内存。

内存监控。

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

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

于 2016-09-13T09:28:18.770 回答
7

MSDN 告诉我们:

IntPtr 类型被设计为一个整数,其大小是特定于平台的。也就是说,这种类型的实例在 32 位硬件和操作系统上预计为 32 位,在 64 位硬件和操作系统上预计为 64 位。

IntPtr 类型可以被支持指针的语言使用,并作为在支持和不支持指针的语言之间引用数据的常用方法。

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

IntPtr 类型符合 CLS,而 UIntPtr 类型则不符合。在公共语言运行库中仅使用 IntPtr 类型。提供 UIntPtr 类型主要是为了与 IntPtr 类型保持架构对称。

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

于 2009-07-18T18:15:44.383 回答
5

嗯,这是处理IntPtr.

第一行写着:

一种特定于平台的类型,用于表示指针或句柄。

至于页面继续声明的指针或句柄是什么:

IntPtr 类型可以被支持指针的语言使用,并作为在支持和不支持指针的语言之间引用数据的常用方法。

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

指针是对包含您感兴趣的一些数据的内存区域的引用。

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

于 2009-07-18T18:14:56.350 回答
2

AnIntPtr是一种值类型,主要用于保存内存地址或句柄。指针是内存地址。指针可以是有类型的(例如int*)或无类型的(例如void*)。Windows 句柄是一个通常与内存地址大小相同(或更小)的值,它表示系统资源(如文件或窗口)。

于 2019-01-13T16:01:19.947 回答