通过使用 IntelliSense 并查看其他人的代码,我遇到了这种IntPtr
类型;每次需要使用它时,我都会简单地放置null
或IntPtr.Zero
发现大多数功能都可以工作。它到底是什么以及何时/为什么使用它?
8 回答
这是一个“本机(特定于平台)大小的整数”。它在内部表示为void*
但公开为整数。您可以在需要存储非托管指针并且不想使用unsafe
代码时使用它。IntPtr.Zero
是有效NULL
的(一个空指针)。
它是一种足够大的值类型,可以存储在本机或不安全代码中使用的内存地址,但不能直接用作安全托管代码中的内存地址。
您可以使用IntPtr.Size
它来确定您是在 32 位还是 64 位进程中运行,因为它分别是 4 或 8 个字节。
这是一个例子:
我正在编写一个与高速相机接口的 C# 程序。相机有自己的驱动程序,它可以自动为我获取图像并将它们加载到计算机的内存中。
因此,当我准备好将最新图像带入我的程序以使用时,相机驱动程序为我提供了一个 IntPtr,该图像已存储在物理内存中,因此我不必浪费时间/资源创建另一个内存块来存储已经在内存中的图像。IntPtr 只是告诉我图像已经在哪里。
直接的解释
IntPtr是一个与指针大小相同的整数。
您可以使用 IntPtr 将指针值存储为非指针类型。此功能在 .NET 中很重要,因为使用指针非常容易出错,因此在大多数情况下都是非法的。通过允许将指针值存储在“安全”数据类型中,不安全代码段之间的管道可以在更安全的高级代码中实现——甚至可以在不直接支持指针的 .NET 语言中实现。
IntPtr 的大小是特定于平台的,但很少需要考虑这个细节,因为系统会自动使用正确的大小。
“IntPtr”这个名字令人困惑——类似的东西Handle
可能更合适。我最初的猜测是“IntPtr”是一个指向整数的指针。IntPtr的MSDN 文档涉及到一些神秘的细节,但没有提供太多关于名称含义的见解。
另一种观点
AnIntPtr
是一个有两个限制的指针:
- 不能直接取消引用
- 它不知道它指向的数据的类型。
换句话说, anIntPtr
就像 a void*
-- 但具有可以(但不应该)用于基本指针运算的额外功能。
为了取消引用 an IntPtr
,您可以将其强制转换为真正的指针(只能在“不安全”上下文中执行的操作),也可以将其传递给辅助例程,例如InteropServices.Marshal
类提供的那些。使用Marshal
该类会产生安全的错觉,因为它不需要您处于明确的“不安全”上下文中。但是,它并没有消除使用指针固有的崩溃风险。
什么是指针?
在所有语言中,指针都是一种存储内存地址的变量,您可以要求它们告诉您它们指向的地址或它们指向的地址的值。
指针可以被认为是一种书签。除了用于快速跳转到书中的一页之外,指针用于跟踪或映射内存块。
想象一下您的程序的内存就像一个 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?
没有充分的理由。
为什么要使用指针?
指针很有趣。由于计算机的大部分内容由内存控制,因此指针使程序员能够更好地控制其程序的内存。
内存监控。
使用指针读取内存块并监视指向的值如何随时间变化。
负责任地更改这些值并跟踪您的更改如何影响您的计算机。
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
嗯,这是处理IntPtr
.
第一行写着:
一种特定于平台的类型,用于表示指针或句柄。
至于页面继续声明的指针或句柄是什么:
IntPtr 类型可以被支持指针的语言使用,并作为在支持和不支持指针的语言之间引用数据的常用方法。
IntPtr 对象也可用于保存句柄。例如,在 System.IO.FileStream 类中广泛使用 IntPtr 的实例来保存文件句柄。
指针是对包含您感兴趣的一些数据的内存区域的引用。
句柄可以是对象的标识符,并在双方都需要访问该对象时在方法/类之间传递。
AnIntPtr
是一种值类型,主要用于保存内存地址或句柄。指针是内存地址。指针可以是有类型的(例如int*
)或无类型的(例如void*
)。Windows 句柄是一个通常与内存地址大小相同(或更小)的值,它表示系统资源(如文件或窗口)。