Ptr to an array? (Was: Possible to ReDim with only a ptr?)

General FreeBASIC programming questions.
mrToad
Posts: 409
Joined: Jun 07, 2005 23:03
Location: USA
Contact:

Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby mrToad » Nov 13, 2019 16:51

I've never done something like this so I was wondering if it's even possible. ReDim an array with only a pointer to it?

Code: Select all

Type udt
   As Long x
End Type

Sub test(a As udt Ptr = 0)
   If a Then
      Print a[0].x
      ReDim Preserve @a(1 To 10)  '' This is obviously wrong, but is it possible to code somehow?
      Print a[0].x
   EndIf
End Sub

ReDim As udt a(1 To 5)
a(1).x = 100

test(@a(1))

Sleep


I am thinking maybe it is not possible because there is no access to the array header with only a pointer to an element. Unless you could find the header somehow?

Just curious. Thanks!
Last edited by mrToad on Nov 16, 2019 2:02, edited 1 time in total.
marcov
Posts: 3019
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: Possible to ReDim with only a ptr?

Postby marcov » Nov 13, 2019 17:16

No. A lot of typing is compiler internal, and gone when the final result runs. While the information might have been there in the compiler, it is not in the EXE
angros47
Posts: 1737
Joined: Jun 21, 2005 19:04

Re: Possible to ReDim with only a ptr?

Postby angros47 » Nov 13, 2019 17:23

In the example, you pass the pointer to the first element of the array, with "test(@a(1))". The informations relative to the size of the array are stored in the descriptor, so the subroutine (that knows the address of the elements, but not of the descriptor) cannot modify it. So no

It is possible to do what you want by passing the whole array (in that way you include the descriptor too, and the subroutine can modify it). You don't even need to pass pointers, FreeBasic will take care of it, since arrays are passed by reference:

Code: Select all

sub routine (array() as integer)
   redim array(90)
   array(15)=10
   array(70)=12
end sub

redim original(20) as integer


routine(original())
?original(15)

?original(70)
mrToad
Posts: 409
Joined: Jun 07, 2005 23:03
Location: USA
Contact:

Re: Possible to ReDim with only a ptr?

Postby mrToad » Nov 16, 2019 1:09

Thanks both of you. I didn't think so, but I imagined maybe, by backing up in memory to the first element and using SizeOf to reach the header or something. It's fine to confirm that it's not possible. :)

@angros47, thanks, I am familiar with that method, and it is best in most cases. The real reason I need a different solution is this:

@everyone -
The code below is not working, but gives you an idea of what I would like to do (and is the reason for my earlier question):

Code: Select all

Type gfx_
   As Long id
End Type

Type obj_
   As Long id
   As gfx_ Ptr p
End Type

Dim As gfx_ gfx1(1 To 10)
Dim As gfx_ gfx2(1 To 10)
Dim As obj_ obj(1 To 1)

gfx1(3).id = 10
gfx2(7).id = 10

obj(1).id = 10
'obj(1).p = @gfx1   '' Nope ...
obj(1).p = @gfx1()   '' Wishfully desiring to point to array descriptor.

For n As Integer = 1 To UBound(obj(1).p)   '' If I was pointing to descriptor, this is would work.
   'If obj(1).p[n]->id = obj(1).id Then   '' Wrong syntax although it doesn't matter with this illustration.
   If obj(1).p[n].id = obj(1).id Then
      Print n & " Found a match."
   Else
      Print n & " No match found."
   EndIf
Next

Sleep

The goal is to have a pointer to a complete UDT array, not just one element. There's probably a clean way to do this, but I haven't thought on it very long.

I got a little closer to a solution in the code below (this code RUNS), but the trouble is not knowing being able to find the UBound of the array that is pointed to (.p) because it is just an element (like my original question.)

Code: Select all

Type gfx_
   As Long id
End Type

Type obj_
   As Long id
   As gfx_ Ptr p
End Type

Dim As gfx_ gfx1(1 To 10)
Dim As gfx_ gfx2(1 To 10)
Dim As obj_ obj(1 To 1)

gfx1(3).id = 10
gfx2(7).id = 10

obj(1).id = 10
obj(1).p = @gfx1(0)   '' In this case, point to data directly after descriptor (as far as I understand.)
'' Bonus question ;)  Although there is no gfx1(0), is it safe to point to it? Because later I will (always) point [1] forward, as the value within [] is an offset value, correct? So in the For/Next to follow, it will begin with gfx1(1).
'' Or, instead, should I point to gfx1(1) and subsequently offset [0]? As in For n As Integer = 1 to etc , .p[n-1].id ?

For n As Integer = 1 To UBound(gfx1)      '' This will work but only for gfx1; I cannot determine the UBound via the (.p) pointer.
   If obj(1).p[n].id = obj(1).id Then
      Print n & " Found a match."
   Else
      Print n & " No match found."
   EndIf
Next

Sleep

One poor solution is for every gfx member to contain the UBound of the array (.count), and use that later (rather than UBound):

Code: Select all

Type gfx_
   As Long id
   As Long count
End Type


But I don't want individual members to refer to what the array descriptor can already provide.

If you have any suggestions, please let me know! Thanks :)
fxm
Posts: 9984
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby fxm » Nov 16, 2019 6:52

- With the current version of fbc 1.08, you can now easily access the array descriptor, and thus do what you want above.
(see the last paragraph "Array Descriptor" of the page 'Arrays' in documentation)
Your code modified accordingly (for fbc 1.08):

Code: Select all

#include "fbc-int/array.bi"

Type gfx_
   As Long id
End Type

Type obj_
   As Long id
   As FBC.FBARRAY Ptr p
End Type

Dim As gfx_ gfx1(1 To 10)
Dim As gfx_ gfx2(1 To 10)
Dim As obj_ obj(1 To 1)

gfx1(3).id = 10
gfx2(7).id = 10

obj(1).id = 10
obj(1).p = FBC.ArrayDescriptorPtr(gfx1())   '' Wishfully desiring to point to array descriptor.

For n As Integer = 1 To obj(1).p->dimTb(0).UBound   '' If I was pointing to descriptor, this is would work.
   If Cptr(gfx_ Ptr, obj(1).p->index_ptr)[n].id = obj(1).id Then
      Print n & " Found a match."
   Else
      Print n & " No match found."
   EndIf
Next

Sleep

- On the other hand, wanting to resize a dynamic array without using REDIM, but directly under the hood thanks to its descriptor is feasible but becomes a really unsafe hacking.
Example (for fbc 1.08):

Code: Select all

#include "fbc-int/array.bi"

Redim As Integer array(-3 To 2)
For I As Integer = Lbound(array) To ubound(array)
  array(I) = 10 + I
Next I

For I As Integer = Lbound(array) To ubound(array)
  Print I, array(I)
Next I
Print

Dim As FBC.FBARRAY Ptr p = FBC.ArrayDescriptorPtr(array())

'' Instead of 'Redim Preserve array(-3 To 6)':
  p->base_ptr = Reallocate(p->base_ptr, 10 * p->element_len)
  p->index_ptr = @Cptr(Integer Ptr, p->base_ptr)[-p->dimTb(0).LBound]
  p->size = 10 * p->element_len
  p->dimTb(0).elements = 10
  p->dimTb(0).UBound = 6

For I As Integer = 3 To Ubound(array)
  array(I) = 10 + I
Next I

For I As Integer = Lbound(array) To ubound(array)
  Print I, array(I)
Next I

Sleep

Note:
Transitional codes can also be defined for the fbc version 1.07.x.
For that, simply replace:
FBC.ArrayDescriptorPtr
with:
fb_ArrayGetDesc


[edit]
Fixed some errors in the second code for updating the descriptor.
Last edited by fxm on Nov 17, 2019 6:33, edited 3 times in total.
Lost Zergling
Posts: 335
Joined: Dec 02, 2011 22:51
Location: France

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby Lost Zergling » Nov 16, 2019 19:32

@mrToad. I understand it is just curiosity, but I don t understand precisely what could be a goal doing this. More speed ? Simpler syntax ? Different feature ? The meaning or purpose of the suggested syntax, even though invalid, is unclear to me. (addendum : if your goal is to parse an array with for next loop, perhaps you could have a look to lzae ? I will extend this stuff later).
fxm
Posts: 9984
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby fxm » Nov 16, 2019 20:15

For me, I consider this rather a challenge, without judging the usefulness of the method.
I only mimed what FreeBASIC probably does under the hood when processing the arrays.
Maybe mrToad needs to be able to pass an array to a procedure using a pointer only as argument.
mrToad
Posts: 409
Joined: Jun 07, 2005 23:03
Location: USA
Contact:

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby mrToad » Nov 16, 2019 21:59

fxm wrote:Maybe mrToad needs to be able to pass an array to a procedure using a pointer only as argument.


Yes, that's what I feel I need to do, exactly! It's nice to see that it's now possible to point to an array descriptor in 1.08! (Although I didn't find the download yet; I'll try your code suggestion for 1.07) And that should do what I hoped for. But all the same, I might be missing something.

fxm wrote:For me, I consider this rather a challenge, without judging the usefulness of the method.


You see, mrToad loves to come up with engenious solutions to problems that he didn't know already have a simple solution. Being all caught up in the fun of discovery (and it is fun indeed), he probably didn't ask for the paved road around the corner. So now, he should explain.

Lost Zergling wrote:@mrToad. I understand it is just curiosity, but I don t understand precisely what could be a goal doing this.


You probe for the practicality, and I appreciate it, because I need it. As for pointing to an array descriptor? I don't know how else to tell my entities (characters, scene backgrounds, items) which graphics array they should be pointing to. (Actually I already had something figured out, but I'm tuning up, tightening up, cutting excess code from, my game engine. Also I want to take advantage of the latest features!)

But let's keep it simple. If you had a UDT array for various characters of a game, and each one needed to point to their own array of graphics, how does the character Type connect to it without a pointer? If you look at my previous code, I'm trying to tell obj(1) to point to a certain graphics array. It can do that with a ptr to a single element, and even access elements around it, but not knowing the bounds. What if you needed a private function of obj(1) to scan through this pointed-to graphics array for some info? That's why I desired to point to the descriptor and access the bounds, to be safe checking all the elements to follow.

So, if any of that makes sense after a couple beers, let me know. And feel free to point out the "This Way" neon sign I've been missing all along. xD
MrSwiss
Posts: 3633
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby MrSwiss » Nov 17, 2019 0:50

Current DEV versions of FBC 1.08.0 can be got from: users.freebasic-portal.de/stw/builds/.

You also might have to get: freebasic_additional_headers.zip, and add it to FBC's inc directory.

For more informaton on new array-header features, check: [FBC-install]/inc/fbc-int/array.bi

(absolutely no beer needed, to come up with this)
Lost Zergling
Posts: 335
Joined: Dec 02, 2011 22:51
Location: France

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby Lost Zergling » Nov 17, 2019 18:55

@mrToad. I thank you for your appreciation. Probing for practicality seems to me a funny but pretty good description for some of my way. I m sure there is not a single way for doing code you expect. Till you are friendly with pointers, 1.08 might be of help. For personnal and prof reasons I have few time for the moment going coding or thinking deeply about your codes, but no doubt I will bring improvments to the tools I designed especially if they can meet some people using them.
ADDENDUM : also related topic : viewtopic.php?f=3&t=27754
Last edited by Lost Zergling on Nov 19, 2019 11:25, edited 1 time in total.
fxm
Posts: 9984
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Ptr to an array? (Was: Possible to ReDim with only a ptr?)

Postby fxm » Nov 18, 2019 20:59

Another way to get a pointer to a dynamic array descriptor is that this descriptor is packaged into a UDT.
For that, it is enough that the dynamic array is declared like a member of the UDT.
Always the same example, but with a code adapted to this different structure:

Code: Select all

Type gfx_
   As Long id
End Type

Type gfxArr_
   As gfx_ gfx(Any)
End Type

Type obj_
   As Long id
   As gfxArr_ Ptr p
End Type

Dim As gfxArr_ gfx1
Redim gfx1.gfx(1 To 10)
Dim As gfxArr_ gfx2
Redim gfx2.gfx(1 To 10)
Dim As obj_ obj(1 To 1)

gfx1.gfx(3).id = 10
gfx2.gfx(7).id = 10

obj(1).id = 10
obj(1).p = @gfx1

For n As Integer = 1 To Ubound(obj(1).p->gfx)
   If obj(1).p->gfx(n).id = obj(1).id Then
      Print n & " Found a match."
   Else
      Print n & " No match found."
   EndIf
Next

Sleep

Return to “General”

Who is online

Users browsing this forum: No registered users and 8 guests