来自 intPtr 的 for 循环,如何?
Posted
技术标签:
【中文标题】来自 intPtr 的 for 循环,如何?【英文标题】:for loop from intPtr, how? 【发布时间】:2021-11-09 10:48:59 【问题描述】:在给定数组开头的 intPtr 的情况下,如何编写 for
循环来迭代浮点数组?
它是 Unity 中的 C#,所以我知道浮点数的字节数是 4。但是当尝试通过简单地使用数字 4 作为递增值从 intPtr 递增时,我只会崩溃。
这是行不通的:
float myFloatVar = 42.42f
for ( int i = varIntPtr ; i < varIntPtr + 12 ; i+=4 )
presumedToBeAnArrayLocation[i] = myFloatVar * i;
【问题讨论】:
显示你的代码的样子。 你能展示你的代码吗?如果没有代码或错误详细信息,几乎不可能进行调试。 不就是你的 IntPtr 变量++吗? @Confused 说最后的评论是非常不恰当的。我要删除它(完成)。请以文明人的身份行事,谢谢。 您似乎没有正确使用 for 循环。在您设置i = myFloatVar
的循环中,这意味着它正在失去它在下一次迭代之前持有的任何其他值。也不清楚这如何与您的 IntPtr
交互(这显然是您的问题的根源,而不是循环本身)。
【参考方案1】:
给定数组开头的 intPtr?
如果你有一个指向数组开头的指针,那么除非该数组被外部固定:你的代码已经不可挽回地被破坏了——非托管指针不会随着 GC 移动而更新,所以你现在有未定义的行为。
如果我们假设它是固定的,或者是非托管内存(因此不受 GC 移动的影响),那么类似于:
float* typed = ptr.ToPointer();
for (int i = 0; i < count; i++)
float v = typed[i];
但是,如果可能,通常最好使用跨度:
var typed = new Span<float>(ptr.ToPointer(), count);
foreach (var v in typed)
【讨论】:
在您的示例中,ptr 是 intPtr,您将其转换为其他类型的指针吗?我被传递了一个 intPtr,并试图从那里开始。有时 intPtr 用于“下一个”数组,有时用于当前数组。性能至关重要,所以我很高兴能尽可能地不安全。 @ConfusedIntPtr
只是一个围绕 void*
非托管指针的包装器,因此您不需要在任何地方使用 unsafe
。我们在这里所做的只是提取void*
并将其强制转换为预期的类型float*
。请注意 - 至少在 .NET 5 及更高版本中 - 跨度通常与不安全代码一样快或更快。我不能说这如何适用于团结。重要的问题仍然存在:数组是否已固定?
数组是NativeArraysomeTypedPointer[i]
表示“计算someTypedPointer + (i * expectedSize)
”;如果你能阅读 IL,你可以在这里看到:sharplab.io/…
"当给定一个 intPtr 时,它必须是一种标准的、正常的遍历数组的方法"——这句话中没有任何东西是标准的或正常的; “这可能是‘正确’的方式,但与问题无关。” - 它与问题有关一切;它是在现代 c# 中迭代任意内存范围的首选方法——这正是您想要做的事情; “但我们也可以只回答他们提出的问题。” - 当有人问如何用锤子正确地拧螺丝时,正确的回答是谈论螺丝刀,即使最初的提问者没有以上是关于来自 intPtr 的 for 循环,如何?的主要内容,如果未能解决你的问题,请参考以下文章
如何在数组中显示来自 Firebase 的用户昵称,然后在 TableView 中显示(For 循环问题)
如何在 javascript 脚本标签中使用 razor for 循环?