-5

How do I write a for loop to iterate over an array of floats, given the intPtr for the start of the array?

It's C# in Unity, so I know the bytes of a float are 4. But am having only crashes when trying to increment from the intPtr by the simple use of the number 4 as a value to increment by.

This is what's not working:

float myFloatVar = 42.42f 

for ( int i = varIntPtr ; i < varIntPtr + 12 ; i+=4 ) {
  presumedToBeAnArrayLocation[i] = myFloatVar * i;
}
Confused
  • 6,048
  • 6
  • 34
  • 75
  • 6
    Show what your code looks like. – 500 - Internal Server Error Sep 14 '21 at 08:44
  • ⬆ Yes, this. We can't help you without your code. ⬆ – ProgrammingLlama Sep 14 '21 at 08:44
  • 1
    Could you show your code? it is almost impossible to debug without code or error detail. – Connor Stoop Sep 14 '21 at 08:44
  • 1
    Isnt it simply your IntPtr variable++ ? – VirussInside Sep 14 '21 at 08:45
  • @VirussInside I'd tried that, but it doesn't seem to be stable, either. I'm thinking it must be 4, to the intPtr, because it's just an address in bytes (single), so 4 must work. – Confused Sep 14 '21 at 08:48
  • @TheGeneral How does that help? The objective is a for loop. – Confused Sep 14 '21 at 08:49
  • 1
    @Confused post your code ~ – TimChang Sep 14 '21 at 08:49
  • To anyone asking to see code, imagine a for loop... that's the code. How do I write a for loop from an intPtr? – Confused Sep 14 '21 at 08:50
  • 1
    A pointer is just one number. To loop, you need the count too. Probably the easiest way to loop, though: `var span = new Span(ptr.ToPointer(), count);` and `foreach` over that. Anything else is going to require lots of `unsafe` code. – Marc Gravell Sep 14 '21 at 08:54
  • 1
    @Confused "please provide the code you currently have" is the simplest possible request to _radically_ improve the quality of your question. you say you have crashes - that means you _have_ code, and you _have_ an error message. ***share them***. period. (hint: "it is not working" is *not* a valid error description) – Franz Gleichmann Sep 14 '21 at 08:54
  • 2
    @Confused that last comment is deeply inappropriate. I'm going to delete it (done). Please act as a civil human, thanks. – Marc Gravell Sep 14 '21 at 08:55
  • 2
    It doesn't look like you're using for loops correctly. Within the loop you set `i = myFloatVar`, meaning that it's losing any other value it held before the next iteration. It's also not clear how this interfaces with your `IntPtr` (which is apparently the source of your issues, rather than the loop itself). – ProgrammingLlama Sep 14 '21 at 08:58
  • I consider it deeply inappropriate to just ask for code like it's a mantra when the question is so incredibly simple. It feels exactly like kneejerk silliness followed by piling on, probably by people that don't know what might be different about an intPtr for loop, as I don't, either. – Confused Sep 14 '21 at 08:59
  • @Llama just put any number inside the for loop, in that variable, just imagine the loop setting ANYTHING... even zero. It's just an example. Whatever assignment I put in there. I am beginning to presume that just using the supposed size of 4 bytes for a float, added to the intPtr, isn't doing the thing I think it should. – Confused Sep 14 '21 at 09:01
  • 1
    but you're setting the index (i) in the loop. – fafase Sep 14 '21 at 09:04
  • Sorry, @fafase, I typed that nonsense example as quick as I could, and just shorthanded that. – Confused Sep 14 '21 at 09:05
  • 1
    You may think that it's kneejerk silliness, but even with the code you've posted above [I can't reproduce any issues](https://dotnetfiddle.net/38QJI5). It's not 100% the same but the concept is similar enough. – ProgrammingLlama Sep 14 '21 at 09:07

1 Answers1

2

given the intPtr for the start of the array?

If you have a pointer to the start of an array, then unless that array is externally pinned: your code is already irretrievably broken - an unmanaged pointer doesn't get updated with GC movement, so you now have undefined behaviour.

If we assume that it is pinned, or is unmanaged memory (and therefore not subject to GC movement), then something like:

float* typed = ptr.ToPointer();
for (int i = 0; i < count; i++)
{
    float v = typed[i];
}

However, it is usually preferable to use spans when possible:

var typed = new Span<float>(ptr.ToPointer(), count);
foreach (var v in typed) {

}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • in your examples, is the ptr an intPtr, and you're converting it to some other kind of pointer? I'm being passed an intPtr, and trying to start from there. sometimes that intPtr is for a 'next' array, sometimes it's for the current array. Performance is critical, so I'm happy to be as unsafe as permitted. – Confused Sep 14 '21 at 09:08
  • 1
    @Confused `IntPtr` is just a wrapper around a `void*` unmanaged pointer, so you don't need `unsafe` everywhere. All we're doing here is extracting the `void*` and coercing it to the expected type, `float*`. Note that - as least in .NET 5 and above - spans are usually just as fast or faster, as unsafe code. I can't say how that applies to unity. The important question remains: is the array pinned? – Marc Gravell Sep 14 '21 at 09:10
  • the array is a NativeArray, which is a special Unity type of array, that's suitable for Jobs and Burst, and this is being done in the Audio thread, wherein everything is pinned because it's single thread, can't do anything else to this array whilst doing this loop. It's the creation of a 256FLOATS buffer, based on whether it's for the current run, or the next run through the data extraction by the audio system. – Confused Sep 14 '21 at 09:16
  • This concept of a void* pointer has done by head in for a few days, so the idea of a float pointer, just to be absolutely clear, is this a type of pointer that's aware of the size of memory it's pointing to, therefore when you do a simple `i++` it's "stepping" the right distance to the next float? – Confused Sep 14 '21 at 09:18
  • 1
    @confused yes: `someTypedPointer[i]` means "compute `someTypedPointer + (i * expectedSize)`"; if you can read IL, you can see that here: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBLANgHwAEAmARgFgAoQgZgAIS6BhOgbyrs4fsNKToCuAOwDOAQwBmMOhNwQxGOgHEYGAGpjcAClnyMAKjoAHNNiGLsASg5d2lLg4YB2YwG1sAXQDcNzgF8qPyA= – Marc Gravell Sep 14 '21 at 09:22
  • BRILLIANT!!! TAHNK YOU! does this mean that my use of i+=4 was failing because it wasn't finding the 4 to be of the same type of maths it sought for byte sizes of a float? Or some other reason? – Confused Sep 14 '21 at 09:25
  • @Confused your code is impossible to decipher, so I can't comment. That's *why* people were asking you to provide realistic code - because they were trying to help you. Tip: people answering may know more about what they need to be able to answer a question than the person asking does; if someone asks for a better example: *provide it*. Specifically, you don't show how any of those locals interact. We could guess, but then any answer is pure guess, too. – Marc Gravell Sep 14 '21 at 09:29
  • Here's another tip. I might just want to know how to loop over an array, starting from an intPtr. that's it, that's all. And I considered adding code, but knew that that would only cloud the issue. there must be a standard, normal way to iterate over an array, when given an intPtr to it. That's all I was asking for. – Confused Sep 14 '21 at 09:37
  • I very deliberately didn't add code, because I wanted to see what it looked like, done properly, to simply loop over an array, starting with the knowledge of an intPtr. I'm still not clear on that, because everyone wanted to talk about my code. I want to see what the best way to do this is, and then make decisions about how it's applicable to what I'm doing, since I don't know how to loop over an array from an intPtr. Sometimes examples don't provide answers, only more questions. Sometimes they might just reveal how it's best done. – Confused Sep 14 '21 at 09:39
  • And you've jumped straight to two things that are odd, and not direct. One of them is span, I didn't ask anything about that. It might be the "right" way, but it's got nothing to do with the question. And the other way you've suggested is changing the pointer, and you don't even bother to say that that's what you're doing, or why. I know it's fashionable to want to talk about the nature of someone's code, but we could also just answer the questions they ask, too. I know. Not suitable commentary. etc. – Confused Sep 14 '21 at 09:43
  • 2
    "must be a standard, normal way to iterate over an array, when given an intPtr" - nothing in that sentence is standard or normal; "It might be the "right" way, but it's got nothing to do with the question." - it has *everything* to do with the question; it is the preferred way to iterate over arbitrary memory ranges in modern c# - exactly the thing you're trying to do; "but we could also just answer the questions they ask, too." - when someone asks how to put screws in with a hammer correctly, the correct response is to talk about screwdrivers, even if the original asker didn't – Marc Gravell Sep 14 '21 at 09:53
  • No, the correct response is to explain that hammers damage screws, and then explain why that's the case. I'm still none the wiser, because your metaphors don't even explain themselves, as it pertains to direct memory access of arrays via a starting pointer. – Confused Sep 14 '21 at 10:09
  • @Confused I found your dealings with Jon Skeet in your previous question to be a little abrasive, using phrases such as "Bury this into your head", and now again with Marc. You may not mean to come across like that, I appreciate that, but that's my interpretation. – ProgrammingLlama Sep 14 '21 at 13:12