Page 1 of 2

Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 12:02 pm
by infratec
Hi,

since I want to optimize the code from doctorized, I need something like this:

Code: Select all

Structure MIB_IFROW
  dwIndex.l
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  *table.MIB_IFROW[0]
EndStructure

Define MIBIfTable.MIB_IFTABLE1
If I do this, I can do

Code: Select all

MIBIfTable\table = AllocateMemory(SizeOf(MIB_IFROW) * 2)
and also

Code: Select all

Debug MIBIfTable\table[1]\dwIndex
But SizeOf(MIB_IFTABLE1) returns 4 and not 8.
I think that's strange.

Complete code:

Code: Select all

Structure MIB_IFROW
  dwIndex.l
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  *table.MIB_IFROW[0]
EndStructure

Define MIBIfTable.MIB_IFTABLE1

Debug SizeOf(MIB_IFTABLE1)

MIBIfTable\table = AllocateMemory(SizeOf(MIB_IFROW) * 2)

ShowMemoryViewer(@MIBIfTable, SizeOf(MIBIfTable))

MIBIfTable\table[1]\dwIndex = 88

Debug MIBIfTable\table[1]\dwIndex
But if I implement this in the original code the program hangs inside the API call wich uses this structure.

I use PB 5.30 x86.

Is there an other trick :?:

Bernd

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 1:49 pm
by Little John
infratec wrote:But SizeOf(MIB_IFTABLE1) returns 4 and not 8.
I think that's strange.
IMHO this is a bug in PB.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 2:42 pm
by auser
I don't see a bug here (except probably that PB allows creation of an static array with 0 size without warning).

Code: Select all

Structure MIB_IFROW
  dwIndex.l
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  *table.MIB_IFROW[2]
EndStructure

Define MIBIfTable.MIB_IFTABLE1

Debug SizeOf(MIB_IFTABLE1)

MIBIfTable\table[0] = AllocateMemory(SizeOf(MIB_IFROW))
MIBIfTable\table[1] = AllocateMemory(SizeOf(MIB_IFROW))

ShowMemoryViewer(@MIBIfTable, SizeOf(MIBIfTable))

MIBIfTable\table[1]\dwIndex = 88

Debug MIBIfTable\table[1]\dwIndex

Code: Select all

Structure dummy
  somelong.l
  somestring.s
  somethingelse.i
EndStructure 


Structure test_1
  somelong.l
  char.a[0]
EndStructure 

Debug(SizeOf(test_1))
; somelong = 4 bytes (type long)
; char.a[?] = crap ...because it's an array with 0 itmes of type a 
; -----------------------
; PB says: 4 bytes 


Structure test_2
  somelong.l
  char.a[2]
EndStructure 

Debug(SizeOf(test_2))
; somelong = 4 bytes (type long)
; char.a[0] = 1 byte (type a)
; char.a[1] = 1 byte (type a)
; -----------------------
; PB says: 6 bytes


Structure test_3
  somelong.l
  *char.dummy[0]
EndStructure

Debug(SizeOf(test_3))
; somelong = 4 bytes
; *char.dummy[?] = crap ...because it's an array with 0 items of type pointer to structure of type dummy
; -----------------------
; PB says: 4 bytes


Structure test_4
  somelong.l
  *char.dummy[2]
EndStructure

Debug(SizeOf(test_4))
; somelong = 4 bytes (type long)
; *char.dummy[0] = 4 bytes (type pointer to structure of type dummy)
; *char.dummy[1] = 4 bytes (type pointer to structure of type dummy)
; -----------------------
; PB says: 12 bytes

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 2:59 pm
by luis
auser wrote:I don't see a bug here (except probably that PB allows creation of an static array with 0 size without warning).
In PB something like this

Code: Select all

Structure foo
 a.i[0]
EndStructure 
is legal to be able to easily overlap the structure to a memory area with a size equal n times SizeOf(Integer)

a.i[1] would make the structure 4 bytes wide on x86 (one array element at 0), a.i[2] would make it 8 bytes wide (elements at 0 and 1) and so on, but a.i[0] doesn't mean anything as you noted unless you introduce the special meaning supported by PB in this specific case, kind of placeholder with an unknown max index.

Code: Select all

Dim mem(2)

mem(0) = 123
mem(1) = 124
mem(2) = 125

Structure foo
 a.i[0]
EndStructure 

Define *p.foo = @mem(0)

Debug *p\a[0]
Debug *p\a[1]
Debug *p\a[2]

Structure bar
 a.i[1]
EndStructure 

Debug SizeOf(bar) ; this is 4

Debug SizeOf(foo) ; this is 0, and in fact it's more an "unknown" than anything else

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:03 pm
by graph100
This should be in the help of PureBasic.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:24 pm
by infratec
Hi,

Code: Select all

*table.MIB_IFROW[0]
is not an array with size 0, it is a pointer.
So I expected that the pointer is available, even when the size of the array is 0.

I can only work around with an extra pointer in a struct:

Code: Select all

Structure MIB_IFROW
  dwIndex.l
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  *table
EndStructure

Structure Test
  table.MIB_IFROW[0]
EndStructure

Define MIBIfTable.MIB_IFTABLE1
Define *Ptr.Test

Debug SizeOf(MIB_IFTABLE1)

MIBIfTable\table = AllocateMemory(SizeOf(MIB_IFROW) * 2)
*Ptr = MIBIfTable\table

ShowMemoryViewer(@MIBIfTable, SizeOf(MIBIfTable))
 
*Ptr\table[1]\dwIndex = 88

Debug *Ptr\table[1]\dwIndex
But than the access looks not like it should :cry:

Bernd

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:31 pm
by luis
infratec wrote:Hi,
is not an array with size 0, it is a pointer.
No, it's an array of structured pointers with size 0.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:34 pm
by infratec
But even with my workaround from above, the API call hangs.
I think he needs the memory at the position of the pointer and no pointer.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:52 pm
by luis
Sorry, don't see any api call, I can only reply about the "strangeness" of the sizeof(), it's indeed strange but it's consistent with the example above (it's a static array with size 0).
Maybe the choice of not occupying space at all inside the structure can be debatable, I'm not sure.
But in reality it does not exist until you overlap it to something, while an empty pointer exists even when not initialized.
Using a pointer for this kind array is indeed strange.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 3:58 pm
by auser
I did not know that that memory-overlap is supported. I'm not really sure what you need exactly. If you don't need pointer why you don't use just table.MIB_IFROW[2] afterwards? Maybe you could try this:

Code: Select all

Structure MIB_IFROW
  dwIndex.l
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  table.MIB_IFROW[0]
EndStructure

Define MIBIfTable.MIB_IFTABLE1

Debug SizeOf(MIB_IFTABLE1)

PokeI(@MIBIfTable+4,AllocateMemory(SizeOf(MIB_IFROW) * 2))

ShowMemoryViewer(@MIBIfTable, SizeOf(MIBIfTable))

MIBIfTable\table[1]\dwIndex = 88

Debug MIBIfTable\table[1]\dwIndex

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 4:25 pm
by infratec
Hi,

it's for this:

http://www.purebasic.fr/english/viewtop ... 28#p451528

The API call is:

Code: Select all

...

lSize = 0
    lErrors = GetIfTable_(@MIB_IFTABLE, @lSize, 0)
    
;     If lErrors = 122
;       Debug lSize - SizeOf(LONG)
;       *MIB_IFTABLE = AllocateMemory(lSize - SizeOf(LONG) - SizeOf(Integer))
;       MIB_IFTABLE\table = @*MIB_IFTABLE
;       Debug MIB_IFTABLE\table
;     EndIf
    
    ;lSize = SizeOf(MIB_IFTABLE1)
    lErrors = GetIfTable_(@MIB_IFTABLE, @lSize, 0)
    
    Debug MIB_IFTABLE\dwNumEntries

...

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 4:48 pm
by auser
The MIB_IFROW structure looks pretty different to the version you've posted in your example: http://msdn.microsoft.com/en-us/library ... 85%29.aspx ...and it looks like pdwSize is telling you the size of the buffer anyway. So I think you could just give it an pointer to a buffer with one item of MIB_IFROW table[1] as first try and do some AllocateMemory afterwards. Maybe it's easier to just use some *void = AllocateMemory(return_size_of_pdwSize) and give it again to the API-function and finally do some *mystruc.MIB_IFTABLE = *void to give it some structure afterwards.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 6:20 pm
by infratec
@ausser

Here in my example I shortened the structure a bit :mrgreen:
It was only to demonstrate the problem.
This saved minimum 1 page of this thread.

Yes, I think also that the best is to allocate a buffer and afterwords place a pointer with the structure over it.
But still I have the problem that there is an array of an unkown size inside the struct.
Ok, I can set the pointer manually to the next entry.

But since I'm lazy and PB should be able to handle this, I searched for a 'better' solution.

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 7:54 pm
by Little John
luis wrote:
infratec wrote:Hi,
is not an array with size 0, it is a pointer.
No, it's an array of structured pointers with size 0.
I also thought that it is a pointer to an array, rather than an array of pointers. :oops:
Thanks for the clarification, Luis!

Re: Pointer to an array inside of a structure

Posted: Thu Aug 21, 2014 10:46 pm
by idle
think you just need to do this

Code: Select all

Structure MIB_IFROW_STRUCT
  wszName.u[#MAX_INTERFACE_NAME_LEN];
  dwIndex.l;
  dwType.l; 
  ;...
EndStructure    

Structure MIB_IFROW
   Row.MIB_IFROW_STRUCT[0]                          ;access the memory with the pattern of the structure, has no size it's just a pattern 
EndStructure

Structure MIB_IFTABLE1
  dwNumEntries.l
  *table.MIB_IFROW                    ;<- pointer to the access pattern 
EndStructure

  MIB_IFTABLE.MIB_IFTABLE1      ;< define a var or pointer    
  MIB_IFTABLE\table = AllocateMemory(Size)  ;or size * sizeof(MIB_IFROW_STRUCT)  

  MIB_IFTABLE\table\Row[0]\dwIndex   ;access the array of MIB_IFROW_STRUCT