什么是一个IntPtr究竟是什么?
通过使用IntelliSense并查看其他人的代码,我遇到了这种IntPtr
types; 每次需要使用我只是把null
或IntPtr.Zero
并发现大部分function工作。 究竟是什么以及何时/为什么使用?
这是一个“本地(特定平台)大小的整数”。 它在内部表示为void*
但是作为整数暴露。 只要需要存储非托pipe指针并且不想使用unsafe
代码,就可以使用它。 IntPtr.Zero
是NULL
(空指针)。
这是一个足够大的值types来存储本地或不安全代码中使用的内存地址,但不能直接用作安全托pipe代码中的内存地址。
您可以使用IntPtr.Size
来确定您是在32位还是64位进程中运行,因为它们分别是4或8个字节。
直接解释
IntPtr是一个与指针大小相同的整数 。
您可以使用IntPtr将指针值存储在非指针types中。 这个特性在.NET中很重要,因为使用指针是非常容易出错的,因此在大多数情况下是非法的。 通过允许将指针值存储在“安全”数据types中, 不安全的代码段之间的pipe道可以用更安全的高级代码实现 – 甚至是不直接支持指针的.NET语言。
IntPtr的大小是平台特定的,但是这个细节很less需要考虑,因为系统会自动使用正确的大小。
名字“IntPtr”令人困惑 – 像Handle
这样的东西可能更合适。 我最初的猜测是“IntPtr”是一个指向一个整数。 IntPtr的MSDN文档进入了一些晦涩的细节,没有提供太多的名字的含义的见解。
另一个angular度
一个IntPtr
是一个有两个限制的指针:
- 它不能直接解除引用
- 它不知道它指向的数据的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?
没有什么好的理由。
为什么使用指针?
指针很有趣。 有了这么多的计算机被内存控制,指针使程序员能够更好地控制程序的内存。
内存监视。
使用指针读取内存块,并监视指向值随着时间的变化。
以负责任的方式更改这些值,并跟踪您的更改如何影响您的计算机。