通过使用IntelliSense并查看其他人的代码,我遇到了这种IntPtr
类型。每次需要使用它时,我都会简单地放置null
或,IntPtr.Zero
并发现大多数功能都可以使用。究竟是什么?何时/为什么使用?
通过使用IntelliSense并查看其他人的代码,我遇到了这种IntPtr
类型。每次需要使用它时,我都会简单地放置null
或,IntPtr.Zero
并发现大多数功能都可以使用。究竟是什么?何时/为什么使用?
Answers:
这是“本地(特定于平台)的大小整数”。它在内部表示为,void*
但作为整数公开。您可以在需要存储非托管指针并且不想使用unsafe
代码的任何时候使用它。IntPtr.Zero
有效NULL
(空指针)。
IntPtr
非常合理,因为它是一个整数(如数学整数)和一个指针(如指针)。该Int
部分与int类型无关-它是一个概念,而不是特定类型。公平地说,CLI规范唯一说的是它确实是“整数,本机大小”。哦,好吧:)
它是一个足够大的值类型,可以存储本地或不安全代码中使用的内存地址,但不能直接用作安全托管代码中的内存地址。
您可以使用它IntPtr.Size
来确定您是在32位还是64位进程中运行,因为它将分别为4字节或8字节。
IntPtr
无论体系结构如何,它们也用于表示32位句柄(尽管Size
在这种情况下仍为8)。CLI规范仅指出它是“本机大小”的整数,但实际上并没有说太多。
这是一个例子:
我正在编写一个与高速相机接口的C#程序。相机具有自己的驱动程序,可自动获取图像并将其加载到计算机的内存中。
因此,当我准备将最新的图像引入程序中时,相机驱动程序会为我提供一个IntPtr,以将图像已存储在物理内存中的位置,因此我不必浪费时间/资源来创建另一个图像内存块以存储已在内存中的图像。IntPtr只是告诉我图像已经在哪里。
一个IntPtr的是一个整数,其是大小相同的指针。
您可以使用IntPtr将指针值存储为非指针类型。此功能在.NET中非常重要,因为使用指针很容易出错,因此在大多数情况下是非法的。通过允许将指针值存储在“安全”数据类型中,可以在更安全的高级代码中甚至在不直接支持指针的.NET语言中实现不安全代码段之间的连接。
IntPtr的大小是特定于平台的,但是由于系统会自动使用正确的大小,因此很少需要考虑此细节。
名称“ IntPtr”令人困惑- Handle
可能更合适。我最初的猜测是,“IntPtr的”是一个指针到一个整数。有关IntPtr的MSDN文档,在没有提供有关名称含义的深入了解的情况下,它的细节有些神秘。
An IntPtr
是一个有两个限制的指针:
换句话说,an IntPtr
就像void*
- 一样,但具有可以(但不应)用于基本指针算术的额外功能。
为了取消对an的引用IntPtr
,您可以将其强制转换为真正的指针(该操作只能在“不安全”的上下文中执行),也可以将其传递给该类提供的帮助程序InteropServices.Marshal
。使用Marshal
类会给人一种安全的假象,因为它不需要您处于显式的“不安全”上下文中。但是,它不能消除使用指针所固有的崩溃风险。
什么是指针?
在所有语言中,指针都是存储内存地址的一种变量,您可以要求它们告诉您所指向的地址或所指向地址的值。
可以将指针视为某种书签。除了使用指针而不是用来快速跳转到书中的页面之外,使用指针来跟踪或映射内存块。
想象一下程序的内存就像一个65535字节的大数组。
指针听话指向
指针每个记住一个内存地址,因此它们每个都指向内存中的一个地址。
作为一个整体,指针会记住并重新调用内存地址,并遵守您的每条命令。
你是他们的国王。
C#中的指针
特别是在C#中,指针是一个整数变量,用于存储0到65534之间的内存地址。
同样针对C#的指针是int类型的,因此是有符号的。
但是,您不能使用负编号的地址,也不能访问65534以上的地址。任何尝试这样做都会抛出System.AccessViolationException。
像这样声明一个称为MyPointer的指针:
int * MyPointer;
C#中的指针是一个int,但是C#中的内存地址从0开始,一直扩展到65534。
尖锐的东西应格外小心
不安全一词旨在吓intended您,原因很充分:指针是尖的东西,尖的东西,例如剑,斧头,指针等,应格外小心。
指针使程序员可以严格控制系统。因此,犯错误可能会造成更严重的后果。
为了使用指针,必须在程序的属性中启用不安全的代码,并且必须仅在标记为不安全的方法或块中使用指针。
不安全块的示例
unsafe
{
// Place code carefully and responsibly here.
}
如何使用指针
声明或实例化变量或对象后,它们将存储在内存中。
int *MyPointer;
MyPointer = &MyVariable;
将地址分配给指针后,将适用以下条件:
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?
没有充分的理由。
为什么要使用指针?
指针很有趣。由于大量的计算机由内存控制,因此指针使程序员可以更好地控制程序的内存。
内存监视。
使用指针读取内存块并监视所指向的值如何随时间变化。
负责任地更改这些值,并跟踪更改对计算机的影响。
65534
指针范围似乎非常错误。您应该提供参考。
System.IntPtr
。我想在末尾看到更新的答案,还请解释什么System.IntPtr
以及它与C#中不安全指针的关系。
MSDN告诉我们:
IntPtr类型设计为整数,其大小是特定于平台的。也就是说,这种类型的实例在32位硬件和操作系统上应该是32位,在64位硬件和操作系统上应该是64位。
IntPtr类型可由支持指针的语言使用,并作为在支持和不支持指针的语言之间引用数据的常用方式。
IntPtr对象也可以用于保存句柄。例如,在System.IO.FileStream类中广泛使用IntPtr的实例来保存文件句柄。
IntPtr类型兼容CLS,而UIntPtr类型不兼容。公共语言运行时中仅使用IntPtr类型。提供UIntPtr类型主要是为了保持与IntPtr类型的体系结构对称性。
http://msdn.microsoft.com/zh-CN/library/system.intptr(VS.71).aspx