来自 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 用于“下一个”数组,有时用于当前数组。性能至关重要,所以我很高兴能尽可能地不安全。 @Confused IntPtr 只是一个围绕 void* 非托管指针的包装器,因此您不需要在任何地方使用 unsafe。我们在这里所做的只是提取void* 并将其强制转换为预期的类型float*。请注意 - 至少在 .NET 5 及更高版本中 - 跨度通常与不安全代码一样快或更快。我不能说这如何适用于团结。重要的问题仍然存在:数组是否已固定? 数组是NativeArray,它是一种特殊的Unity类型的数组,适用于Jobs和Burst,这是在Audio线程中完成的,其中所有内容都是固定的,因为它是单一的线程,在执行此循环时无法对此数组执行任何其他操作。它是创建一个 256FLOATS 缓冲区,这取决于它是用于当前运行,还是通过音频系统提取的数据进行下一次运行。 @confused 是:someTypedPointer[i] 表示“计算someTypedPointer + (i * expectedSize)”;如果你能阅读 IL,你可以在这里看到:sharplab.io/… "当给定一个 intPtr 时,它必须是一种标准的、正常的遍历数组的方法"——这句话中没有任何东西是标准的或正常的; “这可能是‘正确’的方式,但与问题无关。” - 它与问题有关一切;它是在现代 c# 中迭代​​任意内存范围的首选方法——这正是您想要做的事情; “但我们也可以只回答他们提出的问题。” - 当有人问如何用锤子正确地拧螺丝时,正确的回答是谈论螺丝刀,即使最初的提问者没有

以上是关于来自 intPtr 的 for 循环,如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何等待来自 for 循环的多个异步调用?

如何在数组中显示来自 Firebase 的用户昵称,然后在 TableView 中显示(For 循环问题)

如何在 javascript 脚本标签中使用 razor for 循环?

来自 % for % 的 Django 模板变量循环到 Javascript

来自 for 循环的分段错误

如何在 React 的地图中使用 for 循环 [重复]