IntPtr算术
我试图以这种方式分配一个结构数组:
struct T { int a; int b; } data = Marshal.AllocHGlobal(count*Marshal.SizeOf(typeof(T)); ...
我想访问分配的数据“绑定”一个结构到分配给AllocHGlobal的数组中的每个元素…像这样的东西
T v; v = (T)Marshal.PtrToStructure(data+1, typeof(T));
但我没有找到任何方便的方法… 为什么IntPtr缺乏算术 ? 我该如何以“安全”的方式解决这个问题?
有人可以确认PtrToStructure函数将数据复制到struct变量中吗? 换句话说,修改结构体是否反映了结构数组数据中的修改?
当然,我想对使用struct的IntPtr指向的数据进行操作,而不是每次都复制数据,避免不安全的代码。
谢谢大家!
你有四个我能想到的选择,两个只使用“安全”代码,两个使用不安全代码。 不安全的选项可能会明显加快。
安全:
不安全:
如果您可以使用不安全的代码并关注性能,那么最后一个选项可能是最干净的,因为您唯一不安全的代码是您调用本机例程的地方。 如果性能不是问题(也许如果数组的大小相对较小),或者如果你不能使用不安全的代码(也许你没有完全信任),那么第一个选项可能是最干净的,但是,正如我所提到的,如果在调用本机例程之间访问的元素数量只是数组中元素数量的一小部分,那么第二个选项会更快。
注意:
不安全的操作假设你的结构是blittable 。 如果没有,那么安全例程是您唯一的选择。
“为什么
IntPtr
缺乏算术?”
IntPtr
只存储一个内存地址。 它没有关于该内存位置内容的任何信息。 以这种方式,它类似于void*
。 要启用指针运算,您必须知道指向的对象的大小。
从根本上说, IntPtr
主要设计为在托管上下文中用作不透明句柄(即,您不会在托管代码中直接取消引用而只是保持传递给非托管代码。) unsafe
context提供了可以直接操作的指针。
实际上, IntPtr
类型没有自己的算术运算符。 C#支持适当的(不安全的)指针算法,但IntPtr
和Marshal
类的存在是为了“更安全”地使用指针。
我想你想要的东西如下:
int index = 1; // 2nd element of array var v = (T)Marshal.PtrToStructure(new IntPtr(data.ToInt32() + index * Marshal.SizeOf(typeof(T)), typeof(T));
另外,请注意IntPtr
在int
和IntPtr
之间没有隐式转换,所以没有运气。
通常,如果您要使用指针进行任何远程复杂操作,最好选择不安全的代码。
您可以使用IntPtr.ToInt32()
来使用指针结构的整数存储器地址,但要注意平台“位”(32/64)。
对于典型的指针算术,使用指针(在文档中查找fixed
和unsafe
):
T data = new T[count]; fixed (T* ptr = &data) { for (int i = 0; i < count; i++) { // now you can use *ptr + i or ptr[i] } }
编辑:
我在思考IntPtr
允许您处理指向数据的指针而无需显式操作指针地址。 这允许您与COM和本机代码互操作,而无需声明不安全的上下文。 运行时强加的唯一要求是非托管代码权限。 出于这些目的,似乎大多数编组方法只接受整个IntPtr
数据,而不是纯integer
或long
类型,因为它提供了一个薄层,可以防止操纵结构的内容。 您可以直接操作IntPtr
的内部,但要么需要不安全的指针(再次是不安全的上下文)或reflection。 最后,IntPtr会自动采用平台的指针大小。
上述就是C#学习教程:IntPtr算术分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1015909.html